Convert proto IndexedFields to bytes in Lucene and Fake index See change 339790 for the background. We now support storing protos directly in indexes. In the follow up changes, we convert some byte fields to be stored as protos. For all existing index implementations, those fields will be still stored as bytes (i.e the proto values will be converted to bytes on document creation). New index implementations may choose to store protos directly. This makes it possible to e.g. define searches on proto fields. Release-Notes: skip Change-Id: I655cdaa5933964baf06e83464d1aeb1a05d91d1d
diff --git a/java/com/google/gerrit/index/SchemaFieldDefs.java b/java/com/google/gerrit/index/SchemaFieldDefs.java index e0b5dd2..db45b8d 100644 --- a/java/com/google/gerrit/index/SchemaFieldDefs.java +++ b/java/com/google/gerrit/index/SchemaFieldDefs.java
@@ -100,4 +100,12 @@ public interface Setter<I, T> { void set(I object, T value); } + + public static boolean isProtoField(SchemaField<?, ?> schemaField) { + if (!(schemaField instanceof IndexedField<?, ?>.SearchSpec)) { + return false; + } + IndexedField<?, ?> indexedField = ((IndexedField<?, ?>.SearchSpec) schemaField).getField(); + return indexedField.isProtoType() || indexedField.isProtoIterableType(); + } }
diff --git a/java/com/google/gerrit/index/testing/AbstractFakeIndex.java b/java/com/google/gerrit/index/testing/AbstractFakeIndex.java index 591ae26..5838ff1 100644 --- a/java/com/google/gerrit/index/testing/AbstractFakeIndex.java +++ b/java/com/google/gerrit/index/testing/AbstractFakeIndex.java
@@ -28,6 +28,7 @@ import com.google.gerrit.index.Index; import com.google.gerrit.index.QueryOptions; import com.google.gerrit.index.Schema; +import com.google.gerrit.index.SchemaFieldDefs; import com.google.gerrit.index.SchemaFieldDefs.SchemaField; import com.google.gerrit.index.project.ProjectData; import com.google.gerrit.index.project.ProjectIndex; @@ -269,7 +270,8 @@ Project.nameKey((String) doc.get(ChangeField.PROJECT_SPEC.getName())), Change.id(Integer.valueOf((String) doc.get(ChangeField.LEGACY_ID_STR.getName())))); for (SchemaField<ChangeData, ?> field : getSchema().getSchemaFields().values()) { - field.setIfPossible(cd, new FakeStoredValue(doc.get(field.getName()))); + boolean isProtoField = SchemaFieldDefs.isProtoField(field); + field.setIfPossible(cd, new FakeStoredValue(doc.get(field.getName()), isProtoField)); } return cd; }
diff --git a/java/com/google/gerrit/lucene/AbstractLuceneIndex.java b/java/com/google/gerrit/lucene/AbstractLuceneIndex.java index 6eac6f7..c158c65 100644 --- a/java/com/google/gerrit/lucene/AbstractLuceneIndex.java +++ b/java/com/google/gerrit/lucene/AbstractLuceneIndex.java
@@ -38,16 +38,19 @@ import com.google.gerrit.index.QueryOptions; import com.google.gerrit.index.Schema; import com.google.gerrit.index.Schema.Values; +import com.google.gerrit.index.SchemaFieldDefs; import com.google.gerrit.index.SchemaFieldDefs.SchemaField; import com.google.gerrit.index.query.DataSource; import com.google.gerrit.index.query.FieldBundle; import com.google.gerrit.index.query.ListResultSet; import com.google.gerrit.index.query.ResultSet; +import com.google.gerrit.proto.Protos; import com.google.gerrit.server.config.SitePaths; import com.google.gerrit.server.index.IndexUtils; import com.google.gerrit.server.index.options.AutoFlush; import com.google.gerrit.server.logging.LoggingContextAwareExecutorService; import com.google.gerrit.server.logging.LoggingContextAwareScheduledExecutorService; +import com.google.protobuf.MessageLite; import java.io.IOException; import java.sql.Timestamp; import java.util.Set; @@ -366,8 +369,12 @@ doc.add(new TextField(name, (String) value, store)); } } else if (type == FieldType.STORED_ONLY) { + boolean isProtoField = SchemaFieldDefs.isProtoField(values.getField()); for (Object value : values.getValues()) { - doc.add(new StoredField(name, (byte[]) value)); + // Lucene stores protos as bytes + doc.add( + new StoredField( + name, isProtoField ? Protos.toByteArray((MessageLite) value) : (byte[]) value)); } } else { throw FieldType.badFieldType(type);