Merge "Delete SQL index support"
This commit is contained in:
		@@ -1852,17 +1852,12 @@ A link:http://lucene.apache.org/[Lucene] index is used.
 | 
			
		||||
* `SOLR`
 | 
			
		||||
+
 | 
			
		||||
A link:http://lucene.apache.org/solr/[Solr] index is used.
 | 
			
		||||
+
 | 
			
		||||
* `SQL`
 | 
			
		||||
+
 | 
			
		||||
No secondary index.  Not all query operators are supported.  Other
 | 
			
		||||
query operators are routed through the standard SQL query engine.
 | 
			
		||||
 | 
			
		||||
+
 | 
			
		||||
By default, `SQL`.
 | 
			
		||||
By default, `LUCENE`.
 | 
			
		||||
+
 | 
			
		||||
After enabling the secondary index, the index must be built using
 | 
			
		||||
the link:pgm-reindex.html[reindex program] before restarting the
 | 
			
		||||
After changing the secondary index type, the index must be rebuilt
 | 
			
		||||
using the link:pgm-reindex.html[reindex program] before restarting the
 | 
			
		||||
Gerrit server.
 | 
			
		||||
 | 
			
		||||
[[ldap]]Section ldap
 | 
			
		||||
 
 | 
			
		||||
@@ -1,26 +0,0 @@
 | 
			
		||||
// Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
//
 | 
			
		||||
// 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
 | 
			
		||||
//
 | 
			
		||||
// http://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.gerrit.acceptance;
 | 
			
		||||
 | 
			
		||||
import org.eclipse.jgit.lib.Config;
 | 
			
		||||
 | 
			
		||||
public class AbstractDaemonTestWithSecondaryIndex extends AbstractDaemonTest {
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  protected GerritServer startServer(Config cfg, boolean memory)
 | 
			
		||||
      throws Exception {
 | 
			
		||||
    return GerritServer.start(cfg, memory, true);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -18,7 +18,6 @@ import com.google.common.collect.ImmutableList;
 | 
			
		||||
import com.google.gerrit.lucene.LuceneIndexModule;
 | 
			
		||||
import com.google.gerrit.pgm.Daemon;
 | 
			
		||||
import com.google.gerrit.pgm.Init;
 | 
			
		||||
import com.google.gerrit.pgm.Reindex;
 | 
			
		||||
import com.google.gerrit.server.config.FactoryModule;
 | 
			
		||||
import com.google.gerrit.server.config.GerritServerConfig;
 | 
			
		||||
import com.google.gerrit.server.index.ChangeSchemas;
 | 
			
		||||
@@ -51,12 +50,6 @@ public class GerritServer {
 | 
			
		||||
 | 
			
		||||
  /** Returns fully started Gerrit server */
 | 
			
		||||
  static GerritServer start(Config base, boolean memory) throws Exception {
 | 
			
		||||
    return start(base, memory, false);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Returns fully started Gerrit server */
 | 
			
		||||
  static GerritServer start(Config base, boolean memory, boolean index)
 | 
			
		||||
      throws Exception {
 | 
			
		||||
    final CyclicBarrier serverStarted = new CyclicBarrier(2);
 | 
			
		||||
    final Daemon daemon = new Daemon(new Runnable() {
 | 
			
		||||
      public void run() {
 | 
			
		||||
@@ -78,25 +71,16 @@ public class GerritServer {
 | 
			
		||||
      mergeTestConfig(cfg);
 | 
			
		||||
      cfg.setBoolean("httpd", null, "requestLog", false);
 | 
			
		||||
      cfg.setBoolean("sshd", null, "requestLog", false);
 | 
			
		||||
      if (index) {
 | 
			
		||||
        cfg.setString("index", null, "type", "lucene");
 | 
			
		||||
        cfg.setBoolean("index", "lucene", "testInmemory", true);
 | 
			
		||||
        daemon.setLuceneModule(new LuceneIndexModule(
 | 
			
		||||
            ChangeSchemas.getLatest().getVersion(),
 | 
			
		||||
            Runtime.getRuntime().availableProcessors(), null));
 | 
			
		||||
      }
 | 
			
		||||
      cfg.setBoolean("index", "lucene", "testInmemory", true);
 | 
			
		||||
      daemon.setLuceneModule(new LuceneIndexModule(
 | 
			
		||||
          ChangeSchemas.getLatest().getVersion(),
 | 
			
		||||
          Runtime.getRuntime().availableProcessors(), null));
 | 
			
		||||
      daemon.setDatabaseForTesting(ImmutableList.<Module>of(
 | 
			
		||||
          new InMemoryTestingDatabaseModule(cfg)));
 | 
			
		||||
      daemon.start();
 | 
			
		||||
    } else {
 | 
			
		||||
      Config cfg = base != null ? base : new Config();
 | 
			
		||||
      if (index) {
 | 
			
		||||
        cfg.setString("index", null, "type", "lucene");
 | 
			
		||||
      }
 | 
			
		||||
      site = initSite(cfg);
 | 
			
		||||
      if (index) {
 | 
			
		||||
        reindex(site);
 | 
			
		||||
      }
 | 
			
		||||
      daemonService = Executors.newSingleThreadExecutor();
 | 
			
		||||
      daemonService.submit(new Callable<Void>() {
 | 
			
		||||
        public Void call() throws Exception {
 | 
			
		||||
@@ -137,15 +121,6 @@ public class GerritServer {
 | 
			
		||||
    return tmp;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Runs the reindex command. Works only if the site is not currently running. */
 | 
			
		||||
  private static void reindex(File site) throws Exception {
 | 
			
		||||
    Reindex reindex = new Reindex();
 | 
			
		||||
    int rc = reindex.main(new String[] {"-d", site.getPath()});
 | 
			
		||||
    if (rc != 0) {
 | 
			
		||||
      throw new RuntimeException("Reindex failed");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static void mergeTestConfig(Config cfg)
 | 
			
		||||
      throws IOException {
 | 
			
		||||
    InetSocketAddress http = newPort();
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ import static org.junit.Assert.assertTrue;
 | 
			
		||||
import com.google.common.base.Function;
 | 
			
		||||
import com.google.common.collect.ImmutableSet;
 | 
			
		||||
import com.google.common.collect.Iterables;
 | 
			
		||||
import com.google.gerrit.acceptance.AbstractDaemonTestWithSecondaryIndex;
 | 
			
		||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
 | 
			
		||||
import com.google.gerrit.acceptance.AccountCreator;
 | 
			
		||||
import com.google.gerrit.acceptance.RestResponse;
 | 
			
		||||
import com.google.gerrit.acceptance.RestSession;
 | 
			
		||||
@@ -49,7 +49,7 @@ import org.junit.Test;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
public class ConflictsOperatorIT extends AbstractDaemonTestWithSecondaryIndex {
 | 
			
		||||
public class ConflictsOperatorIT extends AbstractDaemonTest {
 | 
			
		||||
 | 
			
		||||
  @Inject
 | 
			
		||||
  private AccountCreator accounts;
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,6 @@ public class GerritConfig implements Cloneable {
 | 
			
		||||
  protected int suggestFrom;
 | 
			
		||||
  protected int changeUpdateDelay;
 | 
			
		||||
  protected AccountGeneralPreferences.ChangeScreen changeScreen;
 | 
			
		||||
  protected boolean index;
 | 
			
		||||
  protected int largeChangeSize;
 | 
			
		||||
 | 
			
		||||
  public String getLoginUrl() {
 | 
			
		||||
@@ -274,14 +273,6 @@ public class GerritConfig implements Cloneable {
 | 
			
		||||
    this.changeScreen = ui;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public boolean hasIndex() {
 | 
			
		||||
    return index;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public void setIndex(boolean index) {
 | 
			
		||||
    this.index = index;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public int getLargeChangeSize() {
 | 
			
		||||
    return largeChangeSize;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -198,7 +198,7 @@ class RelatedChanges extends TabPanel {
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    if (Gerrit.getConfig().hasIndex() && info.mergeable()) {
 | 
			
		||||
    if (info.mergeable()) {
 | 
			
		||||
      StringBuilder conflictsQuery = new StringBuilder();
 | 
			
		||||
      conflictsQuery.append("status:open");
 | 
			
		||||
      conflictsQuery.append(" is:mergeable");
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,6 @@ import com.google.gerrit.server.config.ConfigUtil;
 | 
			
		||||
import com.google.gerrit.server.config.DownloadConfig;
 | 
			
		||||
import com.google.gerrit.server.config.GerritServerConfig;
 | 
			
		||||
import com.google.gerrit.server.contact.ContactStore;
 | 
			
		||||
import com.google.gerrit.server.index.IndexCollection;
 | 
			
		||||
import com.google.gerrit.server.mail.EmailSender;
 | 
			
		||||
import com.google.gerrit.server.ssh.SshInfo;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
@@ -50,7 +49,6 @@ class GerritConfigProvider implements Provider<GerritConfig> {
 | 
			
		||||
  private final GitWebConfig gitWebConfig;
 | 
			
		||||
  private final AllProjectsName wildProject;
 | 
			
		||||
  private final SshInfo sshInfo;
 | 
			
		||||
  private final IndexCollection indexCollection;
 | 
			
		||||
 | 
			
		||||
  private EmailSender emailSender;
 | 
			
		||||
  private final ContactStore contactStore;
 | 
			
		||||
@@ -61,7 +59,6 @@ class GerritConfigProvider implements Provider<GerritConfig> {
 | 
			
		||||
  GerritConfigProvider(final Realm r, @GerritServerConfig final Config gsc,
 | 
			
		||||
      final AuthConfig ac, final GitWebConfig gwc, final AllProjectsName wp,
 | 
			
		||||
      final SshInfo si, final ContactStore cs,
 | 
			
		||||
      final IndexCollection ic,
 | 
			
		||||
      final ServletContext sc, final DownloadConfig dc,
 | 
			
		||||
      final @AnonymousCowardName String acn) {
 | 
			
		||||
    realm = r;
 | 
			
		||||
@@ -70,7 +67,6 @@ class GerritConfigProvider implements Provider<GerritConfig> {
 | 
			
		||||
    downloadConfig = dc;
 | 
			
		||||
    gitWebConfig = gwc;
 | 
			
		||||
    sshInfo = si;
 | 
			
		||||
    indexCollection = ic;
 | 
			
		||||
    wildProject = wp;
 | 
			
		||||
    contactStore = cs;
 | 
			
		||||
    servletContext = sc;
 | 
			
		||||
@@ -130,7 +126,6 @@ class GerritConfigProvider implements Provider<GerritConfig> {
 | 
			
		||||
    config.setChangeScreen(cfg.getEnum(
 | 
			
		||||
        "gerrit", null, "changeScreen",
 | 
			
		||||
        AccountGeneralPreferences.ChangeScreen.CHANGE_SCREEN2));
 | 
			
		||||
    config.setIndex(indexCollection.getSearchIndex() != null);
 | 
			
		||||
    config.setLargeChangeSize(cfg.getInt("change", "largeChange", 500));
 | 
			
		||||
 | 
			
		||||
    config.setReportBugUrl(cfg.getString("gerrit", null, "reportBugUrl"));
 | 
			
		||||
 
 | 
			
		||||
@@ -148,9 +148,7 @@ class AccountServiceImpl extends BaseServiceImplementation implements
 | 
			
		||||
 | 
			
		||||
        if (filter != null) {
 | 
			
		||||
          try {
 | 
			
		||||
            ChangeQueryBuilder builder = queryBuilder.create(currentUser.get());
 | 
			
		||||
            builder.setAllowFileRegex(true);
 | 
			
		||||
            builder.parse(filter);
 | 
			
		||||
            queryBuilder.create(currentUser.get()).parse(filter);
 | 
			
		||||
          } catch (QueryParseException badFilter) {
 | 
			
		||||
            throw new InvalidQueryException(badFilter.getMessage(), filter);
 | 
			
		||||
          }
 | 
			
		||||
 
 | 
			
		||||
@@ -54,6 +54,7 @@ java_library2(
 | 
			
		||||
    ':init-api',
 | 
			
		||||
    '//gerrit-common:server',
 | 
			
		||||
    '//gerrit-extension-api:api',
 | 
			
		||||
    '//gerrit-lucene:lucene',
 | 
			
		||||
    '//gerrit-reviewdb:server',
 | 
			
		||||
    '//gerrit-server:server',
 | 
			
		||||
    '//gerrit-util-cli:cli',
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,7 @@ import com.google.gerrit.server.contact.HttpContactStoreConnection;
 | 
			
		||||
import com.google.gerrit.server.git.ReceiveCommitsExecutorModule;
 | 
			
		||||
import com.google.gerrit.server.git.WorkQueue;
 | 
			
		||||
import com.google.gerrit.server.index.IndexModule;
 | 
			
		||||
import com.google.gerrit.server.index.NoIndexModule;
 | 
			
		||||
import com.google.gerrit.server.index.IndexModule.IndexType;
 | 
			
		||||
import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
 | 
			
		||||
import com.google.gerrit.server.mail.SmtpEmailSender;
 | 
			
		||||
import com.google.gerrit.server.patch.IntraLineWorkerPool;
 | 
			
		||||
@@ -310,18 +310,7 @@ public class Daemon extends SiteProgram {
 | 
			
		||||
    modules.add(new SmtpEmailSender.Module());
 | 
			
		||||
    modules.add(new SignedTokenEmailTokenVerifier.Module());
 | 
			
		||||
    modules.add(new PluginRestApiModule());
 | 
			
		||||
    AbstractModule changeIndexModule;
 | 
			
		||||
    switch (IndexModule.getIndexType(cfgInjector)) {
 | 
			
		||||
      case LUCENE:
 | 
			
		||||
        changeIndexModule = luceneModule != null ? luceneModule : new LuceneIndexModule();
 | 
			
		||||
        break;
 | 
			
		||||
      case SOLR:
 | 
			
		||||
        changeIndexModule = new SolrIndexModule();
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        changeIndexModule = new NoIndexModule();
 | 
			
		||||
    }
 | 
			
		||||
    modules.add(changeIndexModule);
 | 
			
		||||
    modules.add(createIndexModule());
 | 
			
		||||
    if (Objects.firstNonNull(httpd, true)) {
 | 
			
		||||
      modules.add(new CanonicalWebUrlModule() {
 | 
			
		||||
        @Override
 | 
			
		||||
@@ -354,6 +343,18 @@ public class Daemon extends SiteProgram {
 | 
			
		||||
    return cfgInjector.createChildInjector(modules);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private AbstractModule createIndexModule() {
 | 
			
		||||
    IndexType indexType = IndexModule.getIndexType(cfgInjector);
 | 
			
		||||
    switch (indexType) {
 | 
			
		||||
      case LUCENE:
 | 
			
		||||
        return luceneModule != null ? luceneModule : new LuceneIndexModule();
 | 
			
		||||
      case SOLR:
 | 
			
		||||
        return new SolrIndexModule();
 | 
			
		||||
      default:
 | 
			
		||||
        throw new IllegalStateException("unsupported index.type = " + indexType);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private void initSshd() {
 | 
			
		||||
    sshInjector = createSshInjector();
 | 
			
		||||
    sysInjector.getInstance(PluginGuiceEnvironment.class)
 | 
			
		||||
 
 | 
			
		||||
@@ -35,8 +35,6 @@ import com.google.gerrit.server.index.ChangeIndex;
 | 
			
		||||
import com.google.gerrit.server.index.ChangeSchemas;
 | 
			
		||||
import com.google.gerrit.server.index.IndexCollection;
 | 
			
		||||
import com.google.gerrit.server.index.IndexModule;
 | 
			
		||||
import com.google.gerrit.server.index.IndexModule.IndexType;
 | 
			
		||||
import com.google.gerrit.server.index.NoIndexModule;
 | 
			
		||||
import com.google.gerrit.server.patch.PatchListCacheImpl;
 | 
			
		||||
import com.google.gerrit.server.schema.DataSourceProvider;
 | 
			
		||||
import com.google.gerrit.server.schema.DataSourceType;
 | 
			
		||||
@@ -91,9 +89,6 @@ public class Reindex extends SiteProgram {
 | 
			
		||||
  public int run() throws Exception {
 | 
			
		||||
    mustHaveValidSite();
 | 
			
		||||
    dbInjector = createDbInjector(MULTI_USER);
 | 
			
		||||
    if (IndexModule.getIndexType(dbInjector) == IndexType.SQL) {
 | 
			
		||||
      throw die("index.type must be configured (or not SQL)");
 | 
			
		||||
    }
 | 
			
		||||
    limitThreads();
 | 
			
		||||
    if (version == null) {
 | 
			
		||||
      version = ChangeSchemas.getLatest().getVersion();
 | 
			
		||||
@@ -144,7 +139,7 @@ public class Reindex extends SiteProgram {
 | 
			
		||||
        changeIndexModule = new SolrIndexModule(false, threads, outputBase);
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        changeIndexModule = new NoIndexModule();
 | 
			
		||||
        throw new IllegalStateException("unsupported index.type");
 | 
			
		||||
    }
 | 
			
		||||
    modules.add(changeIndexModule);
 | 
			
		||||
    modules.add(new ReviewDbModule());
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,178 @@
 | 
			
		||||
// Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
//
 | 
			
		||||
// 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
 | 
			
		||||
//
 | 
			
		||||
// http://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.gerrit.pgm.init;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.Sets;
 | 
			
		||||
import com.google.gerrit.lucene.LuceneChangeIndex;
 | 
			
		||||
import com.google.gerrit.lucene.LuceneIndexModule;
 | 
			
		||||
import com.google.gerrit.pgm.util.ConsoleUI;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Change;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.PatchSet;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Project;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Project.NameKey;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ReviewDb;
 | 
			
		||||
import com.google.gerrit.server.config.GerritServerConfig;
 | 
			
		||||
import com.google.gerrit.server.config.SitePaths;
 | 
			
		||||
import com.google.gerrit.server.config.TrackingFooter;
 | 
			
		||||
import com.google.gerrit.server.config.TrackingFooters;
 | 
			
		||||
import com.google.gerrit.server.git.GitRepositoryManager;
 | 
			
		||||
import com.google.gerrit.server.index.ChangeIndex;
 | 
			
		||||
import com.google.gerrit.server.index.ChangeSchemas;
 | 
			
		||||
import com.google.gerrit.server.index.IndexModule.IndexType;
 | 
			
		||||
import com.google.gerrit.server.patch.IntraLineDiff;
 | 
			
		||||
import com.google.gerrit.server.patch.IntraLineDiffKey;
 | 
			
		||||
import com.google.gerrit.server.patch.PatchList;
 | 
			
		||||
import com.google.gerrit.server.patch.PatchListCache;
 | 
			
		||||
import com.google.gerrit.server.patch.PatchListKey;
 | 
			
		||||
import com.google.gerrit.server.patch.PatchListNotAvailableException;
 | 
			
		||||
import com.google.gwtorm.server.OrmException;
 | 
			
		||||
import com.google.gwtorm.server.SchemaFactory;
 | 
			
		||||
import com.google.inject.AbstractModule;
 | 
			
		||||
import com.google.inject.Guice;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Injector;
 | 
			
		||||
import com.google.inject.Provides;
 | 
			
		||||
import com.google.inject.ProvisionException;
 | 
			
		||||
import com.google.inject.Singleton;
 | 
			
		||||
 | 
			
		||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
 | 
			
		||||
import org.eclipse.jgit.lib.Config;
 | 
			
		||||
import org.eclipse.jgit.lib.Repository;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.SortedSet;
 | 
			
		||||
 | 
			
		||||
/** Initialize the {@code index} configuration section. */
 | 
			
		||||
@Singleton
 | 
			
		||||
class InitIndex implements InitStep {
 | 
			
		||||
  private final ConsoleUI ui;
 | 
			
		||||
  private final Section index;
 | 
			
		||||
  private final SitePaths site;
 | 
			
		||||
  private final InitFlags initFlags;
 | 
			
		||||
 | 
			
		||||
  @Inject
 | 
			
		||||
  InitIndex(ConsoleUI ui,
 | 
			
		||||
      Section.Factory sections,
 | 
			
		||||
      SitePaths site,
 | 
			
		||||
      InitFlags initFlags) {
 | 
			
		||||
    this.ui = ui;
 | 
			
		||||
    this.index = sections.get("index", null);
 | 
			
		||||
    this.site = site;
 | 
			
		||||
    this.initFlags = initFlags;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public void run() throws IOException {
 | 
			
		||||
    ui.header("Index");
 | 
			
		||||
 | 
			
		||||
    IndexType type = index.select("Type", "type", IndexType.LUCENE);
 | 
			
		||||
    if (site.isNew && type == IndexType.LUCENE) {
 | 
			
		||||
      createLuceneIndex();
 | 
			
		||||
    } else {
 | 
			
		||||
      ui.message("The index must be built before starting Gerrit:\n"
 | 
			
		||||
        + "  java -jar gerrit.war reindex -d site_path\n");
 | 
			
		||||
      initFlags.autoStart = false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private void createLuceneIndex() throws IOException {
 | 
			
		||||
    Injector injector = Guice.createInjector(
 | 
			
		||||
      new LuceneIndexModule(ChangeSchemas.getLatest().getVersion(), 0, null),
 | 
			
		||||
      new MockIndexSupportModule());
 | 
			
		||||
 | 
			
		||||
    ChangeIndex index = injector.getInstance(LuceneChangeIndex.class);
 | 
			
		||||
    index.markReady(true);
 | 
			
		||||
    index.close();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private class MockIndexSupportModule extends AbstractModule {
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void configure() {
 | 
			
		||||
      bind(SitePaths.class).toInstance(site);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Provides @GerritServerConfig Config getConfig() {
 | 
			
		||||
      return new Config();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Provides TrackingFooters newTrackingFooters() {
 | 
			
		||||
      return new TrackingFooters(Collections.<TrackingFooter> emptyList());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Provides ReviewDb getReviewDb() {
 | 
			
		||||
      throw new ProvisionException("database not initialized");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Provides SchemaFactory<ReviewDb> getSchemaFactory() {
 | 
			
		||||
      return new SchemaFactory<ReviewDb>() {
 | 
			
		||||
        @Override
 | 
			
		||||
        public ReviewDb open() throws OrmException {
 | 
			
		||||
          return getReviewDb();
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Provides GitRepositoryManager getGitRepositoryManager() {
 | 
			
		||||
      return new GitRepositoryManager() {
 | 
			
		||||
        @Override
 | 
			
		||||
        public Repository openRepository(Project.NameKey name)
 | 
			
		||||
            throws RepositoryNotFoundException{
 | 
			
		||||
          throw new RepositoryNotFoundException(name.get());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public Repository createRepository(Project.NameKey name)
 | 
			
		||||
            throws RepositoryNotFoundException {
 | 
			
		||||
          throw new RepositoryNotFoundException(name.get());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public SortedSet<Project.NameKey> list() {
 | 
			
		||||
          return Sets.newTreeSet();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public String getProjectDescription(Project.NameKey name) {
 | 
			
		||||
          return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void setProjectDescription(NameKey name, String description) {
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Provides PatchListCache newPatchListCache() {
 | 
			
		||||
      return new PatchListCache() {
 | 
			
		||||
        @Override
 | 
			
		||||
        public PatchList get(PatchListKey key)
 | 
			
		||||
            throws PatchListNotAvailableException {
 | 
			
		||||
          throw new PatchListNotAvailableException("new site, no changes");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public PatchList get(Change change, PatchSet patchSet)
 | 
			
		||||
            throws PatchListNotAvailableException {
 | 
			
		||||
          throw new PatchListNotAvailableException("new site, no changes");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public IntraLineDiff getIntraLineDiff(IntraLineDiffKey key) {
 | 
			
		||||
          return null;
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -46,6 +46,7 @@ public class InitModule extends FactoryModule {
 | 
			
		||||
    if (standalone) {
 | 
			
		||||
      step().to(InitDatabase.class);
 | 
			
		||||
    }
 | 
			
		||||
    step().to(InitIndex.class);
 | 
			
		||||
    step().to(InitAuth.class);
 | 
			
		||||
    step().to(InitSendEmail.class);
 | 
			
		||||
    if (standalone) {
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,6 @@
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.reviewdb.server;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Account;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Branch;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Change;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Project;
 | 
			
		||||
@@ -42,14 +41,6 @@ public interface ChangeAccess extends Access<Change, Change.Id> {
 | 
			
		||||
  @Query("WHERE dest.projectName = ?")
 | 
			
		||||
  ResultSet<Change> byProject(Project.NameKey p) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Deprecated
 | 
			
		||||
  @Query("WHERE owner = ? AND open = true ORDER BY createdOn, changeId")
 | 
			
		||||
  ResultSet<Change> byOwnerOpen(Account.Id id) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Deprecated
 | 
			
		||||
  @Query("WHERE owner = ? AND open = false ORDER BY lastUpdatedOn")
 | 
			
		||||
  ResultSet<Change> byOwnerClosedAll(Account.Id id) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Query("WHERE dest = ? AND status = '" + Change.STATUS_SUBMITTED
 | 
			
		||||
      + "' ORDER BY lastUpdatedOn")
 | 
			
		||||
  ResultSet<Change> submitted(Branch.NameKey dest) throws OrmException;
 | 
			
		||||
@@ -57,65 +48,17 @@ public interface ChangeAccess extends Access<Change, Change.Id> {
 | 
			
		||||
  @Query("WHERE status = '" + Change.STATUS_SUBMITTED + "'")
 | 
			
		||||
  ResultSet<Change> allSubmitted() throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Deprecated
 | 
			
		||||
  @Query("WHERE open = true AND sortKey > ? ORDER BY sortKey LIMIT ?")
 | 
			
		||||
  ResultSet<Change> allOpenPrev(String sortKey, int limit) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Deprecated
 | 
			
		||||
  @Query("WHERE open = true AND sortKey < ? ORDER BY sortKey DESC LIMIT ?")
 | 
			
		||||
  ResultSet<Change> allOpenNext(String sortKey, int limit) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Query("WHERE open = true AND dest.projectName = ?")
 | 
			
		||||
  ResultSet<Change> byProjectOpenAll(Project.NameKey p) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Query("WHERE open = true AND dest = ?")
 | 
			
		||||
  ResultSet<Change> byBranchOpenAll(Branch.NameKey p) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Deprecated
 | 
			
		||||
  @Query("WHERE open = true AND dest.projectName = ? AND sortKey > ?"
 | 
			
		||||
      + " ORDER BY sortKey LIMIT ?")
 | 
			
		||||
  ResultSet<Change> byProjectOpenPrev(Project.NameKey p, String sortKey,
 | 
			
		||||
      int limit) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Query("WHERE open = true AND dest.projectName = ? AND sortKey < ?"
 | 
			
		||||
      + " ORDER BY sortKey DESC LIMIT ?")
 | 
			
		||||
  ResultSet<Change> byProjectOpenNext(Project.NameKey p, String sortKey,
 | 
			
		||||
      int limit) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Deprecated
 | 
			
		||||
  @Query("WHERE open = false AND status = ? AND dest.projectName = ? AND sortKey > ?"
 | 
			
		||||
      + " ORDER BY sortKey LIMIT ?")
 | 
			
		||||
  ResultSet<Change> byProjectClosedPrev(char status, Project.NameKey p,
 | 
			
		||||
      String sortKey, int limit) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Deprecated
 | 
			
		||||
  @Query("WHERE open = false AND status = ? AND dest.projectName = ? AND sortKey < ?"
 | 
			
		||||
      + " ORDER BY sortKey DESC LIMIT ?")
 | 
			
		||||
  ResultSet<Change> byProjectClosedNext(char status, Project.NameKey p,
 | 
			
		||||
      String sortKey, int limit) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Deprecated
 | 
			
		||||
  @Query("WHERE open = false AND status = ? AND sortKey > ? ORDER BY sortKey LIMIT ?")
 | 
			
		||||
  ResultSet<Change> allClosedPrev(char status, String sortKey, int limit)
 | 
			
		||||
      throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Deprecated
 | 
			
		||||
  @Query("WHERE open = false AND status = ? AND sortKey < ? ORDER BY sortKey DESC LIMIT ?")
 | 
			
		||||
  ResultSet<Change> allClosedNext(char status, String sortKey, int limit)
 | 
			
		||||
      throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Deprecated
 | 
			
		||||
  @Query("WHERE open = false AND status = ? AND dest = ? AND sortKey > ?"
 | 
			
		||||
      + " ORDER BY sortKey LIMIT ?")
 | 
			
		||||
  ResultSet<Change> byBranchClosedPrev(char status, Branch.NameKey p,
 | 
			
		||||
      String sortKey, int limit) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Deprecated
 | 
			
		||||
  @Query("WHERE open = false AND status = ? AND dest = ? AND sortKey < ?"
 | 
			
		||||
      + " ORDER BY sortKey DESC LIMIT ?")
 | 
			
		||||
  ResultSet<Change> byBranchClosedNext(char status, Branch.NameKey p,
 | 
			
		||||
      String sortKey, int limit) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Query
 | 
			
		||||
  ResultSet<Change> all() throws OrmException;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -38,14 +38,4 @@ public interface PatchSetApprovalAccess extends
 | 
			
		||||
  @Query("WHERE key.patchSetId = ? AND key.accountId = ?")
 | 
			
		||||
  ResultSet<PatchSetApproval> byPatchSetUser(PatchSet.Id patchSet,
 | 
			
		||||
      Account.Id account) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Deprecated
 | 
			
		||||
  @Query("WHERE changeOpen = true AND key.accountId = ?")
 | 
			
		||||
  ResultSet<PatchSetApproval> openByUser(Account.Id account)
 | 
			
		||||
      throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Deprecated
 | 
			
		||||
  @Query("WHERE changeOpen = false AND key.accountId = ? ORDER BY changeSortKey")
 | 
			
		||||
  ResultSet<PatchSetApproval> closedByUserAll(Account.Id account)
 | 
			
		||||
      throws OrmException;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -28,9 +28,4 @@ public interface TrackingIdAccess extends Access<TrackingId, TrackingId.Key> {
 | 
			
		||||
 | 
			
		||||
  @Query("WHERE key.changeId = ?")
 | 
			
		||||
  ResultSet<TrackingId> byChange(Change.Id change) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Deprecated
 | 
			
		||||
  @Query("WHERE key.trackingKey = ?")
 | 
			
		||||
  ResultSet<TrackingId> byTrackingId(TrackingId.Id trackingId)
 | 
			
		||||
      throws OrmException;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -69,23 +69,11 @@ ON account_project_watches (project_name);
 | 
			
		||||
 | 
			
		||||
-- *********************************************************************
 | 
			
		||||
-- ChangeAccess
 | 
			
		||||
--    covers:             byOwnerOpen
 | 
			
		||||
CREATE INDEX changes_byOwnerOpen
 | 
			
		||||
ON changes (open, owner_account_id, created_on, change_id);
 | 
			
		||||
 | 
			
		||||
--    covers:             byOwnerClosed
 | 
			
		||||
CREATE INDEX changes_byOwnerClosed
 | 
			
		||||
ON changes (open, owner_account_id, last_updated_on);
 | 
			
		||||
 | 
			
		||||
--    covers:             submitted, allSubmitted
 | 
			
		||||
CREATE INDEX changes_submitted
 | 
			
		||||
ON changes (status, dest_project_name, dest_branch_name, last_updated_on);
 | 
			
		||||
 | 
			
		||||
--    covers:             allOpenPrev, allOpenNext
 | 
			
		||||
CREATE INDEX changes_allOpen
 | 
			
		||||
ON changes (open, sort_key);
 | 
			
		||||
 | 
			
		||||
--    covers:             byProjectOpenPrev, byProjectOpenNext
 | 
			
		||||
--    covers:             byProjectOpenAll
 | 
			
		||||
CREATE INDEX changes_byProjectOpen
 | 
			
		||||
ON changes (open, dest_project_name, sort_key);
 | 
			
		||||
 | 
			
		||||
@@ -93,30 +81,10 @@ ON changes (open, dest_project_name, sort_key);
 | 
			
		||||
CREATE INDEX changes_byProject
 | 
			
		||||
ON changes (dest_project_name);
 | 
			
		||||
 | 
			
		||||
--    covers:             allClosedPrev, allClosedNext
 | 
			
		||||
CREATE INDEX changes_allClosed
 | 
			
		||||
ON changes (open, status, sort_key);
 | 
			
		||||
 | 
			
		||||
--    covers:             byBranchClosedPrev, byBranchClosedNext
 | 
			
		||||
CREATE INDEX changes_byBranchClosed
 | 
			
		||||
ON changes (status, dest_project_name, dest_branch_name, sort_key);
 | 
			
		||||
 | 
			
		||||
CREATE INDEX changes_key
 | 
			
		||||
ON changes (change_key);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
-- *********************************************************************
 | 
			
		||||
-- PatchSetApprovalAccess
 | 
			
		||||
--    @PrimaryKey covers: byPatchSet, byPatchSetUser
 | 
			
		||||
--    covers:             openByUser
 | 
			
		||||
CREATE INDEX patch_set_approvals_openByUser
 | 
			
		||||
ON patch_set_approvals (change_open, account_id);
 | 
			
		||||
 | 
			
		||||
--    covers:             closedByUser
 | 
			
		||||
CREATE INDEX patch_set_approvals_closedByU
 | 
			
		||||
ON patch_set_approvals (change_open, account_id, change_sort_key);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
-- *********************************************************************
 | 
			
		||||
-- ChangeMessageAccess
 | 
			
		||||
--    @PrimaryKey covers: byChange
 | 
			
		||||
 
 | 
			
		||||
@@ -117,63 +117,24 @@ ON account_project_watches (project_name);
 | 
			
		||||
 | 
			
		||||
-- *********************************************************************
 | 
			
		||||
-- ChangeAccess
 | 
			
		||||
--    covers:             byOwnerOpen
 | 
			
		||||
CREATE INDEX changes_byOwnerOpen
 | 
			
		||||
ON changes (owner_account_id, created_on, change_id)
 | 
			
		||||
WHERE open = 'Y';
 | 
			
		||||
 | 
			
		||||
--    covers:             byOwnerClosed
 | 
			
		||||
CREATE INDEX changes_byOwnerClosed
 | 
			
		||||
ON changes (owner_account_id, last_updated_on)
 | 
			
		||||
WHERE open = 'N';
 | 
			
		||||
 | 
			
		||||
--    covers:             submitted, allSubmitted
 | 
			
		||||
CREATE INDEX changes_submitted
 | 
			
		||||
ON changes (dest_project_name, dest_branch_name, last_updated_on)
 | 
			
		||||
WHERE status = 's';
 | 
			
		||||
 | 
			
		||||
--    covers:             allOpenPrev, allOpenNext
 | 
			
		||||
CREATE INDEX changes_allOpen
 | 
			
		||||
ON changes (sort_key)
 | 
			
		||||
WHERE open = 'Y';
 | 
			
		||||
 | 
			
		||||
--    covers:             byProjectOpenPrev, byProjectOpenNext
 | 
			
		||||
--    covers:             byProjectOpenAll
 | 
			
		||||
CREATE INDEX changes_byProjectOpen
 | 
			
		||||
ON changes (dest_project_name, sort_key)
 | 
			
		||||
WHERE open = 'Y';
 | 
			
		||||
 | 
			
		||||
--    covers:             allClosedPrev, allClosedNext
 | 
			
		||||
CREATE INDEX changes_allClosed
 | 
			
		||||
ON changes (status, sort_key)
 | 
			
		||||
WHERE open = 'N';
 | 
			
		||||
 | 
			
		||||
--    covers:             byProject
 | 
			
		||||
CREATE INDEX changes_byProject
 | 
			
		||||
ON changes (dest_project_name);
 | 
			
		||||
 | 
			
		||||
--    covers:             byBranchClosedPrev, byBranchClosedNext
 | 
			
		||||
CREATE INDEX changes_byBranchClosed
 | 
			
		||||
ON changes (status, dest_project_name, dest_branch_name, sort_key)
 | 
			
		||||
WHERE open = 'N';
 | 
			
		||||
 | 
			
		||||
CREATE INDEX changes_key
 | 
			
		||||
ON changes (change_key);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
-- *********************************************************************
 | 
			
		||||
-- PatchSetApprovalAccess
 | 
			
		||||
--    @PrimaryKey covers: byPatchSet, byPatchSetUser
 | 
			
		||||
--    covers:             openByUser
 | 
			
		||||
CREATE INDEX patch_set_approvals_openByUser
 | 
			
		||||
ON patch_set_approvals (account_id)
 | 
			
		||||
WHERE change_open = 'Y';
 | 
			
		||||
 | 
			
		||||
--    covers:             closedByUser
 | 
			
		||||
CREATE INDEX patch_set_approvals_closedByU
 | 
			
		||||
ON patch_set_approvals (account_id, change_sort_key)
 | 
			
		||||
WHERE change_open = 'N';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
-- *********************************************************************
 | 
			
		||||
-- ChangeMessageAccess
 | 
			
		||||
--    @PrimaryKey covers: byChange
 | 
			
		||||
 
 | 
			
		||||
@@ -32,49 +32,6 @@ import java.io.IOException;
 | 
			
		||||
 * appropriate.
 | 
			
		||||
 */
 | 
			
		||||
public interface ChangeIndex {
 | 
			
		||||
  /** Instance indicating secondary index is disabled. */
 | 
			
		||||
  public static final ChangeIndex DISABLED = new ChangeIndex() {
 | 
			
		||||
    @Override
 | 
			
		||||
    public Schema<ChangeData> getSchema() {
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void insert(ChangeData cd) throws IOException {
 | 
			
		||||
      // Do nothing.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void replace(ChangeData cd) throws IOException {
 | 
			
		||||
      // Do nothing.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void delete(ChangeData cd) throws IOException {
 | 
			
		||||
      // Do nothing.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void deleteAll() throws IOException {
 | 
			
		||||
      // Do nothing.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ChangeDataSource getSource(Predicate<ChangeData> p, int limit) {
 | 
			
		||||
      throw new UnsupportedOperationException();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void close() {
 | 
			
		||||
      // Do nothing.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void markReady(boolean ready) {
 | 
			
		||||
      throw new UnsupportedOperationException();
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /** @return the schema version used by this index. */
 | 
			
		||||
  public Schema<ChangeData> getSchema();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,6 @@
 | 
			
		||||
package com.google.gerrit.server.index;
 | 
			
		||||
 | 
			
		||||
import com.google.common.base.Function;
 | 
			
		||||
import com.google.common.util.concurrent.Callables;
 | 
			
		||||
import com.google.common.util.concurrent.CheckedFuture;
 | 
			
		||||
import com.google.common.util.concurrent.Futures;
 | 
			
		||||
import com.google.common.util.concurrent.ListeningExecutorService;
 | 
			
		||||
@@ -38,24 +37,6 @@ public abstract class ChangeIndexer {
 | 
			
		||||
    ChangeIndexer create(IndexCollection indexes);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Instance indicating secondary index is disabled. */
 | 
			
		||||
  public static final ChangeIndexer DISABLED = new ChangeIndexer(null) {
 | 
			
		||||
    @Override
 | 
			
		||||
    public CheckedFuture<?, IOException> indexAsync(ChangeData cd) {
 | 
			
		||||
      return Futures.immediateCheckedFuture(null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Callable<?> indexTask(ChangeData cd) {
 | 
			
		||||
      return Callables.returning(null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Callable<?> deleteTask(ChangeData cd) {
 | 
			
		||||
      return Callables.returning(null);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  private static final Function<Exception, IOException> MAPPER =
 | 
			
		||||
      new Function<Exception, IOException>() {
 | 
			
		||||
    @Override
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,6 @@ package com.google.gerrit.server.index;
 | 
			
		||||
 | 
			
		||||
import com.google.common.annotations.VisibleForTesting;
 | 
			
		||||
import com.google.common.collect.Lists;
 | 
			
		||||
import com.google.gerrit.common.Nullable;
 | 
			
		||||
import com.google.gerrit.extensions.events.LifecycleListener;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Singleton;
 | 
			
		||||
@@ -39,11 +38,7 @@ public class IndexCollection implements LifecycleListener {
 | 
			
		||||
    this.searchIndex = new AtomicReference<ChangeIndex>();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @return the current search index version, or null if the secondary index is
 | 
			
		||||
   *     disabled.
 | 
			
		||||
   */
 | 
			
		||||
  @Nullable
 | 
			
		||||
  /** @return the current search index version. */
 | 
			
		||||
  public ChangeIndex getSearchIndex() {
 | 
			
		||||
    return searchIndex.get();
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ import com.google.common.util.concurrent.MoreExecutors;
 | 
			
		||||
import com.google.gerrit.lifecycle.LifecycleModule;
 | 
			
		||||
import com.google.gerrit.server.config.GerritServerConfig;
 | 
			
		||||
import com.google.gerrit.server.git.WorkQueue;
 | 
			
		||||
import com.google.gerrit.server.query.change.BasicChangeRewrites;
 | 
			
		||||
import com.google.gerrit.server.query.change.ChangeQueryRewriter;
 | 
			
		||||
import com.google.inject.AbstractModule;
 | 
			
		||||
import com.google.inject.Injector;
 | 
			
		||||
@@ -37,14 +38,14 @@ import org.eclipse.jgit.lib.Config;
 | 
			
		||||
 */
 | 
			
		||||
public class IndexModule extends LifecycleModule {
 | 
			
		||||
  public enum IndexType {
 | 
			
		||||
    SQL, LUCENE, SOLR
 | 
			
		||||
    LUCENE, SOLR
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Type of secondary index. */
 | 
			
		||||
  public static IndexType getIndexType(Injector injector) {
 | 
			
		||||
    Config cfg = injector.getInstance(
 | 
			
		||||
        Key.get(Config.class, GerritServerConfig.class));
 | 
			
		||||
    return cfg.getEnum("index", null, "type", IndexType.SQL);
 | 
			
		||||
    return cfg.getEnum("index", null, "type", IndexType.LUCENE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private final int threads;
 | 
			
		||||
@@ -63,7 +64,7 @@ public class IndexModule extends LifecycleModule {
 | 
			
		||||
  @Override
 | 
			
		||||
  protected void configure() {
 | 
			
		||||
    bind(ChangeQueryRewriter.class).to(IndexRewriteImpl.class);
 | 
			
		||||
    bind(IndexRewriteImpl.BasicRewritesImpl.class);
 | 
			
		||||
    bind(BasicChangeRewrites.class);
 | 
			
		||||
    bind(IndexCollection.class);
 | 
			
		||||
    listener().to(IndexCollection.class);
 | 
			
		||||
    install(new FactoryModuleBuilder()
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,6 @@ import com.google.gerrit.server.query.NotPredicate;
 | 
			
		||||
import com.google.gerrit.server.query.OrPredicate;
 | 
			
		||||
import com.google.gerrit.server.query.Predicate;
 | 
			
		||||
import com.google.gerrit.server.query.QueryParseException;
 | 
			
		||||
import com.google.gerrit.server.query.QueryRewriter;
 | 
			
		||||
import com.google.gerrit.server.query.change.AndSource;
 | 
			
		||||
import com.google.gerrit.server.query.change.BasicChangeRewrites;
 | 
			
		||||
import com.google.gerrit.server.query.change.ChangeData;
 | 
			
		||||
@@ -33,7 +32,6 @@ import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 | 
			
		||||
import com.google.gerrit.server.query.change.ChangeQueryRewriter;
 | 
			
		||||
import com.google.gerrit.server.query.change.ChangeStatusPredicate;
 | 
			
		||||
import com.google.gerrit.server.query.change.OrSource;
 | 
			
		||||
import com.google.gerrit.server.query.change.SqlRewriterImpl;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Provider;
 | 
			
		||||
 | 
			
		||||
@@ -125,27 +123,21 @@ public class IndexRewriteImpl implements ChangeQueryRewriter {
 | 
			
		||||
 | 
			
		||||
  private final IndexCollection indexes;
 | 
			
		||||
  private final Provider<ReviewDb> db;
 | 
			
		||||
  private final BasicRewritesImpl basicRewrites;
 | 
			
		||||
  private final SqlRewriterImpl sqlRewriter;
 | 
			
		||||
  private final BasicChangeRewrites basicRewrites;
 | 
			
		||||
 | 
			
		||||
  @Inject
 | 
			
		||||
  IndexRewriteImpl(IndexCollection indexes,
 | 
			
		||||
      Provider<ReviewDb> db,
 | 
			
		||||
      BasicRewritesImpl basicRewrites,
 | 
			
		||||
      SqlRewriterImpl sqlRewriter) {
 | 
			
		||||
      BasicChangeRewrites basicRewrites) {
 | 
			
		||||
    this.indexes = indexes;
 | 
			
		||||
    this.db = db;
 | 
			
		||||
    this.basicRewrites = basicRewrites;
 | 
			
		||||
    this.sqlRewriter = sqlRewriter;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Predicate<ChangeData> rewrite(Predicate<ChangeData> in)
 | 
			
		||||
      throws QueryParseException {
 | 
			
		||||
    ChangeIndex index = indexes.getSearchIndex();
 | 
			
		||||
    if (index == null) {
 | 
			
		||||
      return sqlRewriter.rewrite(in);
 | 
			
		||||
    }
 | 
			
		||||
    in = basicRewrites.rewrite(in);
 | 
			
		||||
    int limit = ChangeQueryBuilder.hasLimit(in)
 | 
			
		||||
        ? ChangeQueryBuilder.getLimit(in)
 | 
			
		||||
@@ -271,14 +263,4 @@ public class IndexRewriteImpl implements ChangeQueryRewriter {
 | 
			
		||||
        || p instanceof OrPredicate
 | 
			
		||||
        || p instanceof NotPredicate);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static class BasicRewritesImpl extends BasicChangeRewrites {
 | 
			
		||||
    private static final QueryRewriter.Definition<ChangeData, BasicRewritesImpl> mydef =
 | 
			
		||||
        new QueryRewriter.Definition<ChangeData, BasicRewritesImpl>(
 | 
			
		||||
            BasicRewritesImpl.class, SqlRewriterImpl.BUILDER);
 | 
			
		||||
    @Inject
 | 
			
		||||
    BasicRewritesImpl(Provider<ReviewDb> db, IndexCollection indexes) {
 | 
			
		||||
      super(mydef, db, indexes);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,32 +0,0 @@
 | 
			
		||||
// Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
//
 | 
			
		||||
// 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
 | 
			
		||||
//
 | 
			
		||||
// http://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.gerrit.server.index;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.server.query.change.ChangeQueryRewriter;
 | 
			
		||||
import com.google.gerrit.server.query.change.SqlRewriterImpl;
 | 
			
		||||
import com.google.inject.AbstractModule;
 | 
			
		||||
 | 
			
		||||
public class NoIndexModule extends AbstractModule {
 | 
			
		||||
  // TODO(dborowitz): This module should go away when the index becomes
 | 
			
		||||
  // obligatory, as should the interfaces that exist only to support the
 | 
			
		||||
  // non-index case.
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  protected void configure() {
 | 
			
		||||
    bind(ChangeIndex.class).toInstance(ChangeIndex.DISABLED);
 | 
			
		||||
    bind(ChangeIndexer.class).toInstance(ChangeIndexer.DISABLED);
 | 
			
		||||
    bind(ChangeQueryRewriter.class).to(SqlRewriterImpl.class);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -202,7 +202,6 @@ public class ProjectWatch {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (filter != null) {
 | 
			
		||||
      qb.setAllowFileRegex(true);
 | 
			
		||||
      Predicate<ChangeData> filterPredicate = qb.parse(filter);
 | 
			
		||||
      if (p == null) {
 | 
			
		||||
        p = filterPredicate;
 | 
			
		||||
 
 | 
			
		||||
@@ -24,18 +24,23 @@ import com.google.gerrit.server.index.Schema;
 | 
			
		||||
import com.google.gerrit.server.query.IntPredicate;
 | 
			
		||||
import com.google.gerrit.server.query.Predicate;
 | 
			
		||||
import com.google.gerrit.server.query.QueryRewriter;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.OutOfScopeException;
 | 
			
		||||
import com.google.inject.Provider;
 | 
			
		||||
import com.google.inject.name.Named;
 | 
			
		||||
 | 
			
		||||
public abstract class BasicChangeRewrites extends QueryRewriter<ChangeData> {
 | 
			
		||||
  protected static final ChangeQueryBuilder BUILDER = new ChangeQueryBuilder(
 | 
			
		||||
public class BasicChangeRewrites extends QueryRewriter<ChangeData> {
 | 
			
		||||
  private static final ChangeQueryBuilder BUILDER = new ChangeQueryBuilder(
 | 
			
		||||
      new ChangeQueryBuilder.Arguments( //
 | 
			
		||||
          new InvalidProvider<ReviewDb>(), //
 | 
			
		||||
          new InvalidProvider<ChangeQueryRewriter>(), //
 | 
			
		||||
          null, null, null, null, null, null, null, //
 | 
			
		||||
          null, null, null, null, null, null, null), null);
 | 
			
		||||
 | 
			
		||||
  private static final QueryRewriter.Definition<ChangeData, BasicChangeRewrites> mydef =
 | 
			
		||||
      new QueryRewriter.Definition<ChangeData, BasicChangeRewrites>(
 | 
			
		||||
          BasicChangeRewrites.class, BUILDER);
 | 
			
		||||
 | 
			
		||||
  static Schema<ChangeData> schema(@Nullable IndexCollection indexes) {
 | 
			
		||||
    ChangeIndex index = indexes != null ? indexes.getSearchIndex() : null;
 | 
			
		||||
    return index != null ? index.getSchema() : null;
 | 
			
		||||
@@ -44,10 +49,9 @@ public abstract class BasicChangeRewrites extends QueryRewriter<ChangeData> {
 | 
			
		||||
  protected final Provider<ReviewDb> dbProvider;
 | 
			
		||||
  private final IndexCollection indexes;
 | 
			
		||||
 | 
			
		||||
  protected BasicChangeRewrites(
 | 
			
		||||
      Definition<ChangeData, ? extends QueryRewriter<ChangeData>> def,
 | 
			
		||||
      Provider<ReviewDb> dbProvider, IndexCollection indexes) {
 | 
			
		||||
    super(def);
 | 
			
		||||
  @Inject
 | 
			
		||||
  public BasicChangeRewrites(Provider<ReviewDb> dbProvider, IndexCollection indexes) {
 | 
			
		||||
    super(mydef);
 | 
			
		||||
    this.dbProvider = dbProvider;
 | 
			
		||||
    this.indexes = indexes;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -201,7 +201,6 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
 | 
			
		||||
 | 
			
		||||
  private final Arguments args;
 | 
			
		||||
  private final CurrentUser currentUser;
 | 
			
		||||
  private boolean allowFileRegex;
 | 
			
		||||
 | 
			
		||||
  @Inject
 | 
			
		||||
  public ChangeQueryBuilder(Arguments args, @Assisted CurrentUser currentUser) {
 | 
			
		||||
@@ -219,10 +218,6 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
 | 
			
		||||
    this.currentUser = currentUser;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public void setAllowFileRegex(boolean on) {
 | 
			
		||||
    allowFileRegex = on;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Operator
 | 
			
		||||
  public Predicate<ChangeData> age(String value) {
 | 
			
		||||
    return new AgePredicate(args.dbProvider, value);
 | 
			
		||||
@@ -243,7 +238,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
 | 
			
		||||
 | 
			
		||||
  @Operator
 | 
			
		||||
  public Predicate<ChangeData> comment(String value) throws QueryParseException {
 | 
			
		||||
    ChangeIndex index = requireIndex(FIELD_COMMENT, value);
 | 
			
		||||
    ChangeIndex index = args.indexes.getSearchIndex();
 | 
			
		||||
    return new CommentPredicate(args.dbProvider, index, value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -307,7 +302,6 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ("mergeable".equalsIgnoreCase(value)) {
 | 
			
		||||
      requireIndex(FIELD_IS, "mergeable");
 | 
			
		||||
      return new IsMergeablePredicate(args.dbProvider);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -329,7 +323,6 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
 | 
			
		||||
  @Operator
 | 
			
		||||
  public Predicate<ChangeData> conflicts(String value) throws OrmException,
 | 
			
		||||
      QueryParseException {
 | 
			
		||||
    requireIndex(FIELD_CONFLICTS, value);
 | 
			
		||||
    return new ConflictsPredicate(args.dbProvider, args.patchListCache,
 | 
			
		||||
        args.submitStrategyFactory, args.changeControlGenericFactory,
 | 
			
		||||
        args.userFactory, args.repoManager, args.projectCache,
 | 
			
		||||
@@ -389,12 +382,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
 | 
			
		||||
  @Operator
 | 
			
		||||
  public Predicate<ChangeData> file(String file) throws QueryParseException {
 | 
			
		||||
    if (file.startsWith("^")) {
 | 
			
		||||
      if (!allowFileRegex) {
 | 
			
		||||
        requireIndex(FIELD_FILE, file);
 | 
			
		||||
      }
 | 
			
		||||
      return new RegexFilePredicate(args.dbProvider, args.patchListCache, file);
 | 
			
		||||
    } else {
 | 
			
		||||
      requireIndex(FIELD_FILE, file);
 | 
			
		||||
      return new EqualsFilePredicate(args.dbProvider, args.patchListCache, file);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -456,10 +445,6 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
 | 
			
		||||
  @Operator
 | 
			
		||||
  public Predicate<ChangeData> message(String text) throws QueryParseException {
 | 
			
		||||
    ChangeIndex index = args.indexes.getSearchIndex();
 | 
			
		||||
    if (index == null) {
 | 
			
		||||
      return new LegacyMessagePredicate(args.dbProvider, args.repoManager, text);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return new MessagePredicate(args.dbProvider, index, text);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -753,13 +738,4 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
 | 
			
		||||
    }
 | 
			
		||||
    throw new IllegalArgumentException();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private ChangeIndex requireIndex(String field, String value)
 | 
			
		||||
      throws QueryParseException {
 | 
			
		||||
    ChangeIndex idx = args.indexes.getSearchIndex();
 | 
			
		||||
    if (idx == null) {
 | 
			
		||||
      throw error("secondary index must be enabled for " + field + ":" + value);
 | 
			
		||||
    }
 | 
			
		||||
    return idx;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,69 +0,0 @@
 | 
			
		||||
// Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
//
 | 
			
		||||
// 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
 | 
			
		||||
//
 | 
			
		||||
// http://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.gerrit.server.query.change;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ReviewDb;
 | 
			
		||||
import com.google.gerrit.server.git.GitRepositoryManager;
 | 
			
		||||
import com.google.inject.Provider;
 | 
			
		||||
 | 
			
		||||
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 | 
			
		||||
import org.eclipse.jgit.errors.MissingObjectException;
 | 
			
		||||
import org.eclipse.jgit.lib.Repository;
 | 
			
		||||
import org.eclipse.jgit.revwalk.RevWalk;
 | 
			
		||||
import org.eclipse.jgit.revwalk.filter.MessageRevFilter;
 | 
			
		||||
import org.eclipse.jgit.revwalk.filter.RevFilter;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Predicate to match changes that contains specified text in commit messages
 | 
			
		||||
 * body.
 | 
			
		||||
 */
 | 
			
		||||
public class LegacyMessagePredicate extends RevWalkPredicate {
 | 
			
		||||
 | 
			
		||||
  private static final Logger log = LoggerFactory
 | 
			
		||||
      .getLogger(LegacyMessagePredicate.class);
 | 
			
		||||
 | 
			
		||||
  private final RevFilter rFilter;
 | 
			
		||||
 | 
			
		||||
  public LegacyMessagePredicate(Provider<ReviewDb> db,
 | 
			
		||||
      GitRepositoryManager repoManager, String text) {
 | 
			
		||||
    super(db, repoManager, ChangeQueryBuilder.FIELD_MESSAGE, text);
 | 
			
		||||
    this.rFilter = MessageRevFilter.create(text);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean match(Repository repo, RevWalk rw, Arguments args) {
 | 
			
		||||
    try {
 | 
			
		||||
      return rFilter.include(rw, rw.parseCommit(args.objectId));
 | 
			
		||||
    } catch (MissingObjectException e) {
 | 
			
		||||
      log.error(args.projectName.get() + "\" commit does not exist.", e);
 | 
			
		||||
    } catch (IncorrectObjectTypeException e) {
 | 
			
		||||
      log.error(args.projectName.get() + "\" revision is not a commit.", e);
 | 
			
		||||
    } catch (IOException e) {
 | 
			
		||||
      log.error(
 | 
			
		||||
          "Could not search for commit message in \"" + args.projectName.get()
 | 
			
		||||
              + "\" repository.", e);
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public int getCost() {
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,658 +0,0 @@
 | 
			
		||||
// Copyright (C) 2009 The Android Open Source Project
 | 
			
		||||
//
 | 
			
		||||
// 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
 | 
			
		||||
//
 | 
			
		||||
// http://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.gerrit.server.query.change;
 | 
			
		||||
 | 
			
		||||
import com.google.common.annotations.VisibleForTesting;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Branch;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Change;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ChangeAccess;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ReviewDb;
 | 
			
		||||
import com.google.gerrit.server.query.IntPredicate;
 | 
			
		||||
import com.google.gerrit.server.query.Predicate;
 | 
			
		||||
import com.google.gerrit.server.query.QueryRewriter;
 | 
			
		||||
import com.google.gerrit.server.query.RewritePredicate;
 | 
			
		||||
import com.google.gerrit.server.query.change.ChangeQueryBuilder.LimitPredicate;
 | 
			
		||||
import com.google.gwtorm.server.OrmException;
 | 
			
		||||
import com.google.gwtorm.server.ResultSet;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Provider;
 | 
			
		||||
import com.google.inject.name.Named;
 | 
			
		||||
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
 | 
			
		||||
public class SqlRewriterImpl extends BasicChangeRewrites
 | 
			
		||||
    implements ChangeQueryRewriter {
 | 
			
		||||
  private static final QueryRewriter.Definition<ChangeData, SqlRewriterImpl> mydef =
 | 
			
		||||
      new QueryRewriter.Definition<ChangeData, SqlRewriterImpl>(
 | 
			
		||||
          SqlRewriterImpl.class, BUILDER);
 | 
			
		||||
 | 
			
		||||
  @Inject
 | 
			
		||||
  @VisibleForTesting
 | 
			
		||||
  public SqlRewriterImpl(Provider<ReviewDb> dbProvider) {
 | 
			
		||||
    super(mydef, dbProvider, null);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Predicate<ChangeData> and(Collection<? extends Predicate<ChangeData>> l) {
 | 
			
		||||
    return hasSource(l) ? new AndSource(dbProvider, l) : super.and(l);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Predicate<ChangeData> or(Collection<? extends Predicate<ChangeData>> l) {
 | 
			
		||||
    return hasSource(l) ? new OrSource(l) : super.or(l);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Rewrite("status:open P=(project:*) B=(ref:*)")
 | 
			
		||||
  public Predicate<ChangeData> r05_byBranchOpen(
 | 
			
		||||
      @Named("P") final ProjectPredicate p,
 | 
			
		||||
      @Named("B") final RefPredicate b) {
 | 
			
		||||
    return new ChangeSource(500) {
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a)
 | 
			
		||||
          throws OrmException {
 | 
			
		||||
        return a.byBranchOpenAll(
 | 
			
		||||
            new Branch.NameKey(p.getValueKey(), b.getValue()));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus().isOpen()
 | 
			
		||||
            && p.match(cd)
 | 
			
		||||
            && b.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Rewrite("status:merged P=(project:*) B=(ref:*) S=(sortkey_after:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r05_byBranchMergedPrev(
 | 
			
		||||
      @Named("P") final ProjectPredicate p,
 | 
			
		||||
      @Named("B") final RefPredicate b,
 | 
			
		||||
      @Named("S") final SortKeyPredicate.After s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
 | 
			
		||||
          throws OrmException {
 | 
			
		||||
        return a.byBranchClosedPrev(Change.Status.MERGED.getCode(), //
 | 
			
		||||
            new Branch.NameKey(p.getValueKey(), b.getValue()), key, limit);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
 | 
			
		||||
            && p.match(cd) //
 | 
			
		||||
            && b.match(cd) //
 | 
			
		||||
            && s.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Rewrite("status:merged P=(project:*) B=(ref:*) S=(sortkey_before:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r05_byBranchMergedNext(
 | 
			
		||||
      @Named("P") final ProjectPredicate p,
 | 
			
		||||
      @Named("B") final RefPredicate b,
 | 
			
		||||
      @Named("S") final SortKeyPredicate.Before s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
 | 
			
		||||
          throws OrmException {
 | 
			
		||||
        return a.byBranchClosedNext(Change.Status.MERGED.getCode(), //
 | 
			
		||||
            new Branch.NameKey(p.getValueKey(), b.getValue()), key, limit);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
 | 
			
		||||
            && p.match(cd) //
 | 
			
		||||
            && b.match(cd) //
 | 
			
		||||
            && s.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Rewrite("status:open P=(project:*) S=(sortkey_after:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r10_byProjectOpenPrev(
 | 
			
		||||
      @Named("P") final ProjectPredicate p,
 | 
			
		||||
      @Named("S") final SortKeyPredicate.After s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return new PaginatedSource(500, s.getValue(), l.intValue()) {
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
 | 
			
		||||
          throws OrmException {
 | 
			
		||||
        return a.byProjectOpenPrev(p.getValueKey(), key, limit);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus().isOpen() //
 | 
			
		||||
            && p.match(cd) //
 | 
			
		||||
            && s.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Rewrite("status:open P=(project:*) S=(sortkey_before:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r10_byProjectOpenNext(
 | 
			
		||||
      @Named("P") final ProjectPredicate p,
 | 
			
		||||
      @Named("S") final SortKeyPredicate.Before s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return new PaginatedSource(500, s.getValue(), l.intValue()) {
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
 | 
			
		||||
          throws OrmException {
 | 
			
		||||
        return a.byProjectOpenNext(p.getValueKey(), key, limit);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus().isOpen() //
 | 
			
		||||
            && p.match(cd) //
 | 
			
		||||
            && s.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Rewrite("status:merged P=(project:*) S=(sortkey_after:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r10_byProjectMergedPrev(
 | 
			
		||||
      @Named("P") final ProjectPredicate p,
 | 
			
		||||
      @Named("S") final SortKeyPredicate.After s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
 | 
			
		||||
          throws OrmException {
 | 
			
		||||
        return a.byProjectClosedPrev(Change.Status.MERGED.getCode(), //
 | 
			
		||||
            p.getValueKey(), key, limit);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
 | 
			
		||||
            && p.match(cd) //
 | 
			
		||||
            && s.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Rewrite("status:merged P=(project:*) S=(sortkey_before:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r10_byProjectMergedNext(
 | 
			
		||||
      @Named("P") final ProjectPredicate p,
 | 
			
		||||
      @Named("S") final SortKeyPredicate.Before s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
 | 
			
		||||
          throws OrmException {
 | 
			
		||||
        return a.byProjectClosedNext(Change.Status.MERGED.getCode(), //
 | 
			
		||||
            p.getValueKey(), key, limit);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
 | 
			
		||||
            && p.match(cd) //
 | 
			
		||||
            && s.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Rewrite("status:abandoned P=(project:*) S=(sortkey_after:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r10_byProjectAbandonedPrev(
 | 
			
		||||
      @Named("P") final ProjectPredicate p,
 | 
			
		||||
      @Named("S") final SortKeyPredicate.After s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
 | 
			
		||||
          throws OrmException {
 | 
			
		||||
        return a.byProjectClosedPrev(Change.Status.ABANDONED.getCode(), //
 | 
			
		||||
            p.getValueKey(), key, limit);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
 | 
			
		||||
            && p.match(cd) //
 | 
			
		||||
            && s.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Rewrite("status:abandoned P=(project:*) S=(sortkey_before:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r10_byProjectAbandonedNext(
 | 
			
		||||
      @Named("P") final ProjectPredicate p,
 | 
			
		||||
      @Named("S") final SortKeyPredicate.Before s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
 | 
			
		||||
          throws OrmException {
 | 
			
		||||
        return a.byProjectClosedNext(Change.Status.ABANDONED.getCode(), //
 | 
			
		||||
            p.getValueKey(), key, limit);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
 | 
			
		||||
            && p.match(cd) //
 | 
			
		||||
            && s.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Rewrite("status:open S=(sortkey_after:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r20_byOpenPrev(
 | 
			
		||||
      @Named("S") final SortKeyPredicate.After s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return new PaginatedSource(2000, s.getValue(), l.intValue()) {
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
 | 
			
		||||
          throws OrmException {
 | 
			
		||||
        return a.allOpenPrev(key, limit);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus().isOpen() && s.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Rewrite("status:open S=(sortkey_before:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r20_byOpenNext(
 | 
			
		||||
      @Named("S") final SortKeyPredicate.Before s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return new PaginatedSource(2000, s.getValue(), l.intValue()) {
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
 | 
			
		||||
          throws OrmException {
 | 
			
		||||
        return a.allOpenNext(key, limit);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus().isOpen() && s.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unchecked")
 | 
			
		||||
  @Rewrite("status:merged S=(sortkey_after:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r20_byMergedPrev(
 | 
			
		||||
      @Named("S") final SortKeyPredicate.After s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return new PaginatedSource(50000, s.getValue(), l.intValue()) {
 | 
			
		||||
      {
 | 
			
		||||
        init("r20_byMergedPrev", s, l);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
 | 
			
		||||
          throws OrmException {
 | 
			
		||||
        return a.allClosedPrev(Change.Status.MERGED.getCode(), key, limit);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
 | 
			
		||||
            && s.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unchecked")
 | 
			
		||||
  @Rewrite("status:merged S=(sortkey_before:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r20_byMergedNext(
 | 
			
		||||
      @Named("S") final SortKeyPredicate.Before s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return new PaginatedSource(50000, s.getValue(), l.intValue()) {
 | 
			
		||||
      {
 | 
			
		||||
        init("r20_byMergedNext", s, l);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
 | 
			
		||||
          throws OrmException {
 | 
			
		||||
        return a.allClosedNext(Change.Status.MERGED.getCode(), key, limit);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
 | 
			
		||||
            && s.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unchecked")
 | 
			
		||||
  @Rewrite("status:abandoned S=(sortkey_after:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r20_byAbandonedPrev(
 | 
			
		||||
      @Named("S") final SortKeyPredicate.After s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return new PaginatedSource(50000, s.getValue(), l.intValue()) {
 | 
			
		||||
      {
 | 
			
		||||
        init("r20_byAbandonedPrev", s, l);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
 | 
			
		||||
          throws OrmException {
 | 
			
		||||
        return a.allClosedPrev(Change.Status.ABANDONED.getCode(), key, limit);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
 | 
			
		||||
            && s.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unchecked")
 | 
			
		||||
  @Rewrite("status:abandoned S=(sortkey_before:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r20_byAbandonedNext(
 | 
			
		||||
      @Named("S") final SortKeyPredicate.Before s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return new PaginatedSource(50000, s.getValue(), l.intValue()) {
 | 
			
		||||
      {
 | 
			
		||||
        init("r20_byAbandonedNext", s, l);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
 | 
			
		||||
          throws OrmException {
 | 
			
		||||
        return a.allClosedNext(Change.Status.ABANDONED.getCode(), key, limit);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
 | 
			
		||||
            && s.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unchecked")
 | 
			
		||||
  @Rewrite("status:closed S=(sortkey_after:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r20_byClosedPrev(
 | 
			
		||||
      @Named("S") final SortKeyPredicate.After s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return or(r20_byMergedPrev(s, l), r20_byAbandonedPrev(s, l));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unchecked")
 | 
			
		||||
  @Rewrite("status:closed S=(sortkey_after:*) L=(limit:*)")
 | 
			
		||||
  public Predicate<ChangeData> r20_byClosedNext(
 | 
			
		||||
      @Named("S") final SortKeyPredicate.Before s,
 | 
			
		||||
      @Named("L") final IntPredicate<ChangeData> l) {
 | 
			
		||||
    return or(r20_byMergedNext(s, l), r20_byAbandonedNext(s, l));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unchecked")
 | 
			
		||||
  @Rewrite("status:open O=(owner:*)")
 | 
			
		||||
  public Predicate<ChangeData> r25_byOwnerOpen(
 | 
			
		||||
      @Named("O") final OwnerPredicate o) {
 | 
			
		||||
    return new ChangeSource(50) {
 | 
			
		||||
      {
 | 
			
		||||
        init("r25_byOwnerOpen", o);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a) throws OrmException {
 | 
			
		||||
        return a.byOwnerOpen(o.getAccountId());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus().isOpen() && o.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unchecked")
 | 
			
		||||
  @Rewrite("status:closed O=(owner:*)")
 | 
			
		||||
  public Predicate<ChangeData> r25_byOwnerClosed(
 | 
			
		||||
      @Named("O") final OwnerPredicate o) {
 | 
			
		||||
    return new ChangeSource(5000) {
 | 
			
		||||
      {
 | 
			
		||||
        init("r25_byOwnerClosed", o);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a) throws OrmException {
 | 
			
		||||
        return a.byOwnerClosedAll(o.getAccountId());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus().isClosed() && o.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unchecked")
 | 
			
		||||
  @Rewrite("O=(owner:*)")
 | 
			
		||||
  public Predicate<ChangeData> r26_byOwner(@Named("O") OwnerPredicate o) {
 | 
			
		||||
    return or(r25_byOwnerOpen(o), r25_byOwnerClosed(o));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unchecked")
 | 
			
		||||
  @Rewrite("status:open R=(reviewer:*)")
 | 
			
		||||
  public Predicate<ChangeData> r30_byReviewerOpen(
 | 
			
		||||
      @Named("R") final ReviewerPredicate r) {
 | 
			
		||||
    return new Source() {
 | 
			
		||||
      {
 | 
			
		||||
        init("r30_byReviewerOpen", r);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      public ResultSet<ChangeData> read() throws OrmException {
 | 
			
		||||
        return ChangeDataResultSet.patchSetApproval(dbProvider.get()
 | 
			
		||||
            .patchSetApprovals().openByUser(r.getAccountId()));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        Change change = cd.change(dbProvider);
 | 
			
		||||
        return change != null && change.getStatus().isOpen() && r.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public int getCardinality() {
 | 
			
		||||
        return 50;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public int getCost() {
 | 
			
		||||
        return ChangeCosts.cost(ChangeCosts.APPROVALS_SCAN, getCardinality());
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unchecked")
 | 
			
		||||
  @Rewrite("status:closed R=(reviewer:*)")
 | 
			
		||||
  public Predicate<ChangeData> r30_byReviewerClosed(
 | 
			
		||||
      @Named("R") final ReviewerPredicate r) {
 | 
			
		||||
    return new Source() {
 | 
			
		||||
      {
 | 
			
		||||
        init("r30_byReviewerClosed", r);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @SuppressWarnings("deprecation")
 | 
			
		||||
      @Override
 | 
			
		||||
      public ResultSet<ChangeData> read() throws OrmException {
 | 
			
		||||
        return ChangeDataResultSet.patchSetApproval(dbProvider.get()
 | 
			
		||||
            .patchSetApprovals().closedByUserAll(r.getAccountId()));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        Change change = cd.change(dbProvider);
 | 
			
		||||
        return change != null && change.getStatus().isClosed() && r.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public int getCardinality() {
 | 
			
		||||
        return 5000;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public int getCost() {
 | 
			
		||||
        return ChangeCosts.cost(ChangeCosts.APPROVALS_SCAN, getCardinality());
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unchecked")
 | 
			
		||||
  @Rewrite("R=(reviewer:*)")
 | 
			
		||||
  public Predicate<ChangeData> r31_byReviewer(
 | 
			
		||||
      @Named("R") final ReviewerPredicate r) {
 | 
			
		||||
    return or(r30_byReviewerOpen(r), r30_byReviewerClosed(r));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Rewrite("status:closed")
 | 
			
		||||
  public Predicate<ChangeData> r99_allClosed() {
 | 
			
		||||
    return r20_byClosedNext(
 | 
			
		||||
        new SortKeyPredicate.Before(null, dbProvider, "z"),
 | 
			
		||||
        new LimitPredicate(Integer.MAX_VALUE));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Rewrite("status:submitted")
 | 
			
		||||
  public Predicate<ChangeData> r99_allSubmitted() {
 | 
			
		||||
    return new ChangeSource(50) {
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a) throws OrmException {
 | 
			
		||||
        return a.allSubmitted();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return cd.change(dbProvider).getStatus() == Change.Status.SUBMITTED;
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Rewrite("P=(project:*)")
 | 
			
		||||
  public Predicate<ChangeData> r99_byProject(
 | 
			
		||||
      @Named("P") final ProjectPredicate p) {
 | 
			
		||||
    return new ChangeSource(1000000) {
 | 
			
		||||
      @Override
 | 
			
		||||
      ResultSet<Change> scan(ChangeAccess a) throws OrmException {
 | 
			
		||||
        return a.byProject(p.getValueKey());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Override
 | 
			
		||||
      public boolean match(ChangeData cd) throws OrmException {
 | 
			
		||||
        return p.match(cd);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static boolean hasSource(Collection<? extends Predicate<ChangeData>> l) {
 | 
			
		||||
    for (Predicate<ChangeData> p : l) {
 | 
			
		||||
      if (p instanceof ChangeDataSource) {
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private abstract static class Source extends RewritePredicate<ChangeData>
 | 
			
		||||
      implements ChangeDataSource {
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean hasChange() {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private abstract class ChangeSource extends Source {
 | 
			
		||||
    private final int cardinality;
 | 
			
		||||
 | 
			
		||||
    ChangeSource(int card) {
 | 
			
		||||
      this.cardinality = card;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    abstract ResultSet<Change> scan(ChangeAccess a) throws OrmException;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ResultSet<ChangeData> read() throws OrmException {
 | 
			
		||||
      return ChangeDataResultSet.change(scan(dbProvider.get().changes()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean hasChange() {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getCardinality() {
 | 
			
		||||
      return cardinality;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getCost() {
 | 
			
		||||
      return ChangeCosts.cost(ChangeCosts.CHANGES_SCAN, getCardinality());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private abstract class PaginatedSource extends ChangeSource implements
 | 
			
		||||
      Paginated {
 | 
			
		||||
    private final String startKey;
 | 
			
		||||
    private final int limit;
 | 
			
		||||
 | 
			
		||||
    PaginatedSource(int card, String start, int lim) {
 | 
			
		||||
      super(card);
 | 
			
		||||
      this.startKey = start;
 | 
			
		||||
      this.limit = lim;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int limit() {
 | 
			
		||||
      return limit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    ResultSet<Change> scan(ChangeAccess a) throws OrmException {
 | 
			
		||||
      return scan(a, startKey, limit);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ResultSet<ChangeData> restart(ChangeData last) throws OrmException {
 | 
			
		||||
      return ChangeDataResultSet.change(scan(dbProvider.get().changes(), //
 | 
			
		||||
          last.change(dbProvider).getSortKey(), //
 | 
			
		||||
          limit));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    abstract ResultSet<Change> scan(ChangeAccess a, String key, int limit)
 | 
			
		||||
        throws OrmException;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -14,21 +14,14 @@
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.server.query.change;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Change;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.TrackingId;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ReviewDb;
 | 
			
		||||
import com.google.gerrit.server.index.ChangeField;
 | 
			
		||||
import com.google.gerrit.server.index.IndexPredicate;
 | 
			
		||||
import com.google.gwtorm.server.ListResultSet;
 | 
			
		||||
import com.google.gwtorm.server.OrmException;
 | 
			
		||||
import com.google.gwtorm.server.ResultSet;
 | 
			
		||||
import com.google.inject.Provider;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.HashSet;
 | 
			
		||||
 | 
			
		||||
class TrackingIdPredicate extends IndexPredicate<ChangeData> implements
 | 
			
		||||
    ChangeDataSource {
 | 
			
		||||
class TrackingIdPredicate extends IndexPredicate<ChangeData> {
 | 
			
		||||
  private final Provider<ReviewDb> db;
 | 
			
		||||
 | 
			
		||||
  TrackingIdPredicate(Provider<ReviewDb> db, String trackingId) {
 | 
			
		||||
@@ -46,34 +39,10 @@ class TrackingIdPredicate extends IndexPredicate<ChangeData> implements
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("deprecation")
 | 
			
		||||
  @Override
 | 
			
		||||
  public ResultSet<ChangeData> read() throws OrmException {
 | 
			
		||||
    HashSet<Change.Id> ids = new HashSet<Change.Id>();
 | 
			
		||||
    for (TrackingId sc : db.get().trackingIds() //
 | 
			
		||||
        .byTrackingId(new TrackingId.Id(getValue()))) {
 | 
			
		||||
      ids.add(sc.getChangeId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ArrayList<ChangeData> r = new ArrayList<ChangeData>(ids.size());
 | 
			
		||||
    for (Change.Id id : ids) {
 | 
			
		||||
      r.add(new ChangeData(id));
 | 
			
		||||
    }
 | 
			
		||||
    return new ListResultSet<ChangeData>(r);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean hasChange() {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public int getCardinality() {
 | 
			
		||||
    return ChangeCosts.CARD_TRACKING_IDS;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public int getCost() {
 | 
			
		||||
    return ChangeCosts.cost(ChangeCosts.TR_SCAN, getCardinality());
 | 
			
		||||
    return ChangeCosts.cost(
 | 
			
		||||
        ChangeCosts.TR_SCAN,
 | 
			
		||||
        ChangeCosts.CARD_TRACKING_IDS);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -28,12 +28,12 @@ import com.google.gerrit.reviewdb.client.Change;
 | 
			
		||||
import com.google.gerrit.server.query.AndPredicate;
 | 
			
		||||
import com.google.gerrit.server.query.Predicate;
 | 
			
		||||
import com.google.gerrit.server.query.QueryParseException;
 | 
			
		||||
import com.google.gerrit.server.query.RewritePredicate;
 | 
			
		||||
import com.google.gerrit.server.query.change.AndSource;
 | 
			
		||||
import com.google.gerrit.server.query.change.BasicChangeRewrites;
 | 
			
		||||
import com.google.gerrit.server.query.change.ChangeData;
 | 
			
		||||
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 | 
			
		||||
import com.google.gerrit.server.query.change.OrSource;
 | 
			
		||||
import com.google.gerrit.server.query.change.SqlRewriterImpl;
 | 
			
		||||
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
@@ -56,8 +56,7 @@ public class IndexRewriteTest {
 | 
			
		||||
    rewrite = new IndexRewriteImpl(
 | 
			
		||||
        indexes,
 | 
			
		||||
        null,
 | 
			
		||||
        new IndexRewriteImpl.BasicRewritesImpl(null, indexes),
 | 
			
		||||
        new SqlRewriterImpl(null));
 | 
			
		||||
        new BasicChangeRewrites(null, indexes));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
@@ -202,19 +201,6 @@ public class IndexRewriteTest {
 | 
			
		||||
        out.getChildren());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testNoChangeIndexUsesSqlRewrites() throws Exception {
 | 
			
		||||
    Predicate<ChangeData> in = parse("status:open project:p ref:b");
 | 
			
		||||
    Predicate<ChangeData> out;
 | 
			
		||||
 | 
			
		||||
    out = rewrite(in);
 | 
			
		||||
    assertTrue(out instanceof AndPredicate || out instanceof IndexedChangeQuery);
 | 
			
		||||
 | 
			
		||||
    indexes.setSearchIndex(null);
 | 
			
		||||
    out = rewrite(in);
 | 
			
		||||
    assertTrue(out instanceof RewritePredicate);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private Predicate<ChangeData> parse(String query) throws QueryParseException {
 | 
			
		||||
    return queryBuilder.parse(query);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,29 +0,0 @@
 | 
			
		||||
// Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
//
 | 
			
		||||
// 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
 | 
			
		||||
//
 | 
			
		||||
// http://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.gerrit.server.query.change;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.testutil.InMemoryModule;
 | 
			
		||||
import com.google.inject.Guice;
 | 
			
		||||
import com.google.inject.Injector;
 | 
			
		||||
 | 
			
		||||
import org.eclipse.jgit.lib.Config;
 | 
			
		||||
 | 
			
		||||
public class SqlQueryChangesTest extends AbstractQueryChangesTest {
 | 
			
		||||
  protected Injector createInjector() {
 | 
			
		||||
    Config cfg = InMemoryModule.newDefaultConfig();
 | 
			
		||||
    cfg.setString("index", null, "type", "sql");
 | 
			
		||||
    return Guice.createInjector(new InMemoryModule(cfg));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -43,7 +43,6 @@ import com.google.gerrit.server.git.GitRepositoryManager;
 | 
			
		||||
import com.google.gerrit.server.git.PerThreadRequestScope;
 | 
			
		||||
import com.google.gerrit.server.index.ChangeSchemas;
 | 
			
		||||
import com.google.gerrit.server.index.IndexModule.IndexType;
 | 
			
		||||
import com.google.gerrit.server.index.NoIndexModule;
 | 
			
		||||
import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
 | 
			
		||||
import com.google.gerrit.server.mail.SmtpEmailSender;
 | 
			
		||||
import com.google.gerrit.server.schema.Current;
 | 
			
		||||
@@ -83,6 +82,9 @@ public class InMemoryModule extends FactoryModule {
 | 
			
		||||
    cfg.setString("user", null, "email", "gerrit@localhost");
 | 
			
		||||
    cfg.setBoolean("sendemail", null, "enable", false);
 | 
			
		||||
    cfg.setString("cache", null, "directory", null);
 | 
			
		||||
    cfg.setString("index", null, "type", "lucene");
 | 
			
		||||
    cfg.setBoolean("index", "lucene", "testInmemory", true);
 | 
			
		||||
    cfg.setInt("index", "lucene", "testVersion", 4);
 | 
			
		||||
    return cfg;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -155,7 +157,7 @@ public class InMemoryModule extends FactoryModule {
 | 
			
		||||
 | 
			
		||||
    IndexType indexType = null;
 | 
			
		||||
    try {
 | 
			
		||||
      indexType = cfg.getEnum("index", null, "type", IndexType.SQL);
 | 
			
		||||
      indexType = cfg.getEnum("index", null, "type", IndexType.LUCENE);
 | 
			
		||||
    } catch (IllegalArgumentException e) {
 | 
			
		||||
      // Custom index type, caller must provide their own module.
 | 
			
		||||
    }
 | 
			
		||||
@@ -164,9 +166,6 @@ public class InMemoryModule extends FactoryModule {
 | 
			
		||||
        case LUCENE:
 | 
			
		||||
          install(luceneIndexModule());
 | 
			
		||||
          break;
 | 
			
		||||
        case SQL:
 | 
			
		||||
          install(new NoIndexModule());
 | 
			
		||||
          break;
 | 
			
		||||
        default:
 | 
			
		||||
          throw new ProvisionException(
 | 
			
		||||
              "index type unsupported in tests: " + indexType);
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,6 @@ import com.google.gerrit.server.git.LocalDiskRepositoryManager;
 | 
			
		||||
import com.google.gerrit.server.git.ReceiveCommitsExecutorModule;
 | 
			
		||||
import com.google.gerrit.server.git.WorkQueue;
 | 
			
		||||
import com.google.gerrit.server.index.IndexModule;
 | 
			
		||||
import com.google.gerrit.server.index.NoIndexModule;
 | 
			
		||||
import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
 | 
			
		||||
import com.google.gerrit.server.mail.SmtpEmailSender;
 | 
			
		||||
import com.google.gerrit.server.patch.IntraLineWorkerPool;
 | 
			
		||||
@@ -268,7 +267,7 @@ public class WebAppInitializer extends GuiceServletContextListener
 | 
			
		||||
        changeIndexModule = new SolrIndexModule();
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        changeIndexModule = new NoIndexModule();
 | 
			
		||||
        throw new IllegalStateException("unsupported index.type");
 | 
			
		||||
    }
 | 
			
		||||
    modules.add(changeIndexModule);
 | 
			
		||||
    modules.add(new CanonicalWebUrlModule() {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user