Store PatchSetApprovals instead of labels in the index

The goal of storing SubmitRecord.Labels in the index was to render the
change table, but that requires both the results of the submit rule
evaluator and, in fact, all of the current PatchSetApprovals.

Instead, store PatchSetApprovals, which are trivial to find at
indexing time. Note that we do not just use the formatted label
representation stored in the index because it does not contain all the
necessary columns (e.g. timestamp). These may not be strictly speaking
required for rendering the change table, but having them set to null
in some cases might have caused errors down the line.

Delete the old label-based code entirely and change schema v2 rather
than revving to v3. This mistake was short-lived enough that we don't
expect people to have production data using it, and the old code was
sufficiently complex and incorrect that keeping it around isn't a good
idea.

Change-Id: I805a8fd6c60d4818910aed299260f56ef3006287
This commit is contained in:
Dave Borowitz
2013-09-12 13:25:58 -07:00
parent cce486f760
commit 24b14d5053
8 changed files with 75 additions and 264 deletions

View File

@@ -14,9 +14,7 @@
package com.google.gerrit.server.index;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
@@ -24,11 +22,8 @@ import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.SubmitRecord;
import com.google.gerrit.reviewdb.client.TrackingId;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.ChangeStatusPredicate;
@@ -42,7 +37,6 @@ import java.io.IOException;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
@@ -265,63 +259,28 @@ public class ChangeField {
/** Serialized change object, used for pre-populating results. */
public static final ChangeProtoField CHANGE = new ChangeProtoField();
public static class SubmitLabelProtoField
public static class PatchSetApprovalProtoField
extends FieldDef.Repeatable<ChangeData, byte[]> {
public static final ProtobufCodec<SubmitRecord.Label> CODEC =
CodecFactory.encoder(SubmitRecord.Label.class);
public static final ProtobufCodec<PatchSetApproval> CODEC =
CodecFactory.encoder(PatchSetApproval.class);
private SubmitLabelProtoField() {
super("_label", FieldType.STORED_ONLY, true);
private PatchSetApprovalProtoField() {
super("_approval", FieldType.STORED_ONLY, true);
}
@Override
public Iterable<byte[]> get(ChangeData input, FillArgs args)
throws OrmException {
// Flatten the highest-valued labels to mimic the results from ChangeJson
// with standard labels.
Map<String, SubmitRecord.Label> labels = Maps.newLinkedHashMap();
for (SubmitRecord rec : getSubmitRecords(input, args)) {
if (rec.labels == null) {
continue;
}
for (SubmitRecord.Label r : rec.labels) {
SubmitRecord.Label p = labels.get(r.label);
if (p == null || p.status.compareTo(r.status) < 0) {
labels.put(r.label, r);
}
}
}
return toProtos(CODEC, labels.values());
}
private List<SubmitRecord> getSubmitRecords(ChangeData input,
FillArgs args) throws OrmException {
ChangeControl ctl;
try {
// Use the ChangeControl for InternalUser. This will give bogus
// results for whether or not the change is submittable, but does
// not affect label calculation.
ctl = args.changeControlFor(input.change(args.db));
} catch (NoSuchChangeException e) {
throw new OrmException(e);
}
if (ctl == null) {
return ImmutableList.of();
}
PatchSet ps = input.currentPatchSet(args.db);
if (ps == null) {
return ImmutableList.of();
}
return ctl.canSubmit(args.db.get(), ps, input, true, true, true);
return toProtos(CODEC, input.currentApprovals(args.db));
}
}
/**
* Serialized labels from the submit rule evaluator, used for pre-populating
* Serialized approvals for the current patch set, used for pre-populating
* results.
*/
public static final SubmitLabelProtoField SUBMIT_RECORD_LABEL =
new SubmitLabelProtoField();
public static final PatchSetApprovalProtoField APPROVAL =
new PatchSetApprovalProtoField();
public static String formatLabel(String label, int value) {
return formatLabel(label, value, null);