Merge branch 'stable-3.3' into master
* stable-3.3:
Bazel: Perform some clean ups after rules_closure removal
Update JGit to 5d925ecbb
Move java_tools javac argument into tools parameter.
Exempt commons-io from library compliance
Bump commons-io version to 2.4
Update git submodules
Update git submodules
Update git submodules
Update git submodules
Compact the REST-API output JSON unconditionally
Elasticsearch: Discontinue EOL versions 7.0 and 7.1 support
Elasticsearch: Discontinue EOL version 6.8 thus whole V6 support
Update git submodules
Avoid logging "length=0" exception
Change-Id: I28ee5f258c2072886d1b2674f017b76d9da0757d
diff --git a/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
index e56f470..44a377a 100644
--- a/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
+++ b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
@@ -84,6 +84,9 @@
protected static final String BULK = "_bulk";
protected static final String MAPPINGS = "mappings";
protected static final String ORDER = "order";
+ protected static final String DESC_SORT_ORDER = "desc";
+ protected static final String ASC_SORT_ORDER = "asc";
+ protected static final String UNMAPPED_TYPE = "unmapped_type";
protected static final String SEARCH = "_search";
protected static final String SETTINGS = "settings";
@@ -288,7 +291,7 @@
protected JsonArray getSortArray(String idFieldName) {
JsonObject properties = new JsonObject();
- properties.addProperty(ORDER, "asc");
+ properties.addProperty(ORDER, ASC_SORT_ORDER);
JsonArray sortArray = new JsonArray();
addNamedElement(idFieldName, properties, sortArray);
diff --git a/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java b/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
index 625a598..969ffa5 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
@@ -57,6 +57,9 @@
import com.google.gson.JsonObject;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
+import java.sql.Timestamp;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
@@ -133,14 +136,24 @@
private JsonArray getSortArray() {
JsonObject properties = new JsonObject();
- properties.addProperty(ORDER, "desc");
+ properties.addProperty(ORDER, DESC_SORT_ORDER);
JsonArray sortArray = new JsonArray();
addNamedElement(ChangeField.UPDATED.getName(), properties, sortArray);
+ addNamedElement(ChangeField.MERGED_ON.getName(), getMergedOnSortOptions(), sortArray);
addNamedElement(idField.getName(), properties, sortArray);
return sortArray;
}
+ private JsonObject getMergedOnSortOptions() {
+ JsonObject sortOptions = new JsonObject();
+ sortOptions.addProperty(ORDER, DESC_SORT_ORDER);
+ // Ignore the sort field if it does not exist in index. Otherwise the search would fail on open
+ // changes, because the corresponding documents do not have mergedOn field.
+ sortOptions.addProperty(UNMAPPED_TYPE, ElasticMapping.TIMESTAMP_FIELD_TYPE);
+ return sortOptions;
+ }
+
@Override
protected String getDeleteActions(Change.Id c) {
return getDeleteRequest(c);
@@ -361,6 +374,10 @@
cd);
}
+ if (fields.contains(ChangeField.MERGED_ON.getName())) {
+ decodeMergedOn(source, cd);
+ }
+
return cd;
}
@@ -396,4 +413,18 @@
}
out.setUnresolvedCommentCount(count.getAsInt());
}
+
+ private void decodeMergedOn(JsonObject doc, ChangeData out) {
+ JsonElement mergedOnField = doc.get(ChangeField.MERGED_ON.getName());
+
+ Timestamp mergedOn = null;
+ if (mergedOnField != null) {
+ // Parse from ElasticMapping.TIMESTAMP_FIELD_FORMAT.
+ // We currently use built-in ISO-based dateOptionalTime.
+ // https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#built-in-date-formats
+ DateTimeFormatter isoFormatter = DateTimeFormatter.ISO_INSTANT;
+ mergedOn = Timestamp.from(Instant.from(isoFormatter.parse(mergedOnField.getAsString())));
+ }
+ out.setMergedOn(mergedOn);
+ }
}
diff --git a/java/com/google/gerrit/elasticsearch/ElasticMapping.java b/java/com/google/gerrit/elasticsearch/ElasticMapping.java
index f8c4168..edd05c9 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticMapping.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticMapping.java
@@ -21,6 +21,10 @@
import java.util.Map;
class ElasticMapping {
+
+ protected static final String TIMESTAMP_FIELD_TYPE = "date";
+ protected static final String TIMESTAMP_FIELD_FORMAT = "dateOptionalTime";
+
static MappingProperties createMapping(Schema<?> schema, ElasticQueryAdapter adapter) {
ElasticMapping.Builder mapping = new ElasticMapping.Builder(adapter);
for (FieldDef<?, ?> field : schema.getFields().values()) {
@@ -71,9 +75,9 @@
}
Builder addTimestamp(String name) {
- FieldProperties properties = new FieldProperties("date");
- properties.type = "date";
- properties.format = "dateOptionalTime";
+ FieldProperties properties = new FieldProperties(TIMESTAMP_FIELD_TYPE);
+ properties.type = TIMESTAMP_FIELD_TYPE;
+ properties.format = TIMESTAMP_FIELD_FORMAT;
fields.put(name, properties);
return this;
}
diff --git a/java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java b/java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java
index d05e91c..40ac603 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java
@@ -29,7 +29,6 @@
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.index.query.RegexPredicate;
import com.google.gerrit.index.query.TimestampRangePredicate;
-import com.google.gerrit.server.query.change.AfterPredicate;
import java.time.Instant;
public class ElasticQueryBuilder {
@@ -130,7 +129,9 @@
private <T> QueryBuilder timestampQuery(IndexPredicate<T> p) throws QueryParseException {
if (p instanceof TimestampRangePredicate) {
TimestampRangePredicate<T> r = (TimestampRangePredicate<T>) p;
- if (p instanceof AfterPredicate) {
+ if (r.getMaxTimestamp().getTime() == Long.MAX_VALUE) {
+ // The time range only has the start value, search from the start to the max supported value
+ // Long.MAX_VALUE
return QueryBuilders.rangeQuery(r.getField().getName())
.gte(Instant.ofEpochMilli(r.getMinTimestamp().getTime()));
}