Merge "Delete SQL index support"

This commit is contained in:
Shawn Pearce 2013-11-29 20:48:25 +00:00 committed by Gerrit Code Review
commit da07edd370
34 changed files with 238 additions and 1217 deletions

View File

@ -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

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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;

View File

@ -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;
}

View File

@ -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");

View File

@ -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"));

View File

@ -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);
}

View File

@ -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',

View File

@ -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)

View File

@ -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());

View File

@ -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;
}
};
}
}
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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();
}

View File

@ -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()

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -202,7 +202,6 @@ public class ProjectWatch {
}
if (filter != null) {
qb.setAllowFileRegex(true);
Predicate<ChangeData> filterPredicate = qb.parse(filter);
if (p == null) {
p = filterPredicate;

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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));
}
}

View File

@ -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);

View File

@ -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() {