Skip to content

RTDB: Add startAfter + endBefore protocol support #4351

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -290,10 +290,8 @@ public void run() {
*/
@NonNull
public Query startAfter(@Nullable String value) {
if (value != null && params.getIndex().equals(KeyIndex.getInstance())) {
return startAt(PushIdGenerator.successor(value));
}
return startAt(value, ChildKey.getMaxName().asString());
Node node = value != null ? new StringNode(value, PriorityUtilities.NullPriority()) : EmptyNode.Empty();
return startAfter(node, null);
}

/**
Expand All @@ -306,7 +304,7 @@ public Query startAfter(@Nullable String value) {
*/
@NonNull
public Query startAfter(double value) {
return startAt(value, ChildKey.getMaxName().asString());
return startAfter(new DoubleNode(value, PriorityUtilities.NullPriority()), null);
}

/**
Expand All @@ -319,7 +317,7 @@ public Query startAfter(double value) {
*/
@NonNull
public Query startAfter(boolean value) {
return startAt(value, ChildKey.getMaxName().asString());
return startAfter(new BooleanNode(value, PriorityUtilities.NullPriority()), null);
}

/**
Expand All @@ -334,9 +332,6 @@ public Query startAfter(boolean value) {
*/
@NonNull
public Query startAfter(@Nullable String value, @Nullable String key) {
if (value != null && params.getIndex().equals(KeyIndex.getInstance())) {
value = PushIdGenerator.successor(value);
}
Node node =
value != null ? new StringNode(value, PriorityUtilities.NullPriority()) : EmptyNode.Empty();
return startAfter(node, key);
Expand Down Expand Up @@ -373,7 +368,7 @@ public Query startAfter(boolean value, @Nullable String key) {
}

private Query startAfter(Node node, String key) {
return startAt(node, PushIdGenerator.successor(key));
return startAt(node, key, false);
}

/**
Expand Down Expand Up @@ -426,7 +421,7 @@ public Query startAt(boolean value) {
public Query startAt(@Nullable String value, @Nullable String key) {
Node node =
value != null ? new StringNode(value, PriorityUtilities.NullPriority()) : EmptyNode.Empty();
return startAt(node, key);
return startAt(node, key, true);
}

/**
Expand All @@ -440,7 +435,7 @@ public Query startAt(@Nullable String value, @Nullable String key) {
*/
@NonNull
public Query startAt(double value, @Nullable String key) {
return startAt(new DoubleNode(value, PriorityUtilities.NullPriority()), key);
return startAt(new DoubleNode(value, PriorityUtilities.NullPriority()), key, true);
}

/**
Expand All @@ -455,10 +450,10 @@ public Query startAt(double value, @Nullable String key) {
*/
@NonNull
public Query startAt(boolean value, @Nullable String key) {
return startAt(new BooleanNode(value, PriorityUtilities.NullPriority()), key);
return startAt(new BooleanNode(value, PriorityUtilities.NullPriority()), key, true);
}

private Query startAt(Node node, String key) {
private Query startAt(Node node, String key, Boolean isInclusive) {
Validation.validateNullableKey(key);
if (!(node.isLeafNode() || node.isEmpty())) {
throw new IllegalArgumentException(
Expand All @@ -478,7 +473,7 @@ private Query startAt(Node node, String key) {
childKey = ChildKey.fromString(key);
}
}
QueryParams newParams = params.startAt(node, childKey);
QueryParams newParams = isInclusive ? params.startAt(node, childKey) : params.startAfter(node, childKey);
validateLimit(newParams);
validateQueryEndpoints(newParams);
hardAssert(newParams.isValid());
Expand All @@ -495,10 +490,7 @@ private Query startAt(Node node, String key) {
*/
@NonNull
public Query endBefore(@Nullable String value) {
if (value != null && params.getIndex().equals(KeyIndex.getInstance())) {
return endAt(PushIdGenerator.predecessor(value));
}
return endAt(value, ChildKey.getMinName().asString());
return endBefore(value, null);
}

/**
Expand All @@ -511,7 +503,7 @@ public Query endBefore(@Nullable String value) {
*/
@NonNull
public Query endBefore(double value) {
return endAt(value, ChildKey.getMinName().asString());
return endAt(value, null);
}

/**
Expand All @@ -524,7 +516,7 @@ public Query endBefore(double value) {
*/
@NonNull
public Query endBefore(boolean value) {
return endAt(value, ChildKey.getMinName().asString());
return endBefore(value, null);
}

/**
Expand All @@ -539,9 +531,6 @@ public Query endBefore(boolean value) {
*/
@NonNull
public Query endBefore(@Nullable String value, @Nullable String key) {
if (value != null && params.getIndex().equals(KeyIndex.getInstance())) {
value = PushIdGenerator.predecessor(value);
}
Node node =
value != null ? new StringNode(value, PriorityUtilities.NullPriority()) : EmptyNode.Empty();
return endBefore(node, key);
Expand Down Expand Up @@ -578,7 +567,7 @@ public Query endBefore(boolean value, @Nullable String key) {
}

private Query endBefore(Node node, String key) {
return endAt(node, PushIdGenerator.predecessor(key));
return endAt(node, key, false);
}

/**
Expand Down Expand Up @@ -631,7 +620,7 @@ public Query endAt(boolean value) {
public Query endAt(@Nullable String value, @Nullable String key) {
Node node =
value != null ? new StringNode(value, PriorityUtilities.NullPriority()) : EmptyNode.Empty();
return endAt(node, key);
return endAt(node, key, true);
}

/**
Expand All @@ -645,7 +634,7 @@ public Query endAt(@Nullable String value, @Nullable String key) {
*/
@NonNull
public Query endAt(double value, @Nullable String key) {
return endAt(new DoubleNode(value, PriorityUtilities.NullPriority()), key);
return endAt(new DoubleNode(value, PriorityUtilities.NullPriority()), key, true);
}

/**
Expand All @@ -660,10 +649,10 @@ public Query endAt(double value, @Nullable String key) {
*/
@NonNull
public Query endAt(boolean value, @Nullable String key) {
return endAt(new BooleanNode(value, PriorityUtilities.NullPriority()), key);
return endAt(new BooleanNode(value, PriorityUtilities.NullPriority()), key, true);
}

private Query endAt(Node node, String key) {
private Query endAt(Node node, String key, Boolean isInclusive) {
Validation.validateNullableKey(key);
if (!(node.isLeafNode() || node.isEmpty())) {
throw new IllegalArgumentException("Can only use simple values for endAt()");
Expand All @@ -672,7 +661,7 @@ private Query endAt(Node node, String key) {
if (params.hasEnd()) {
throw new IllegalArgumentException("Can't call endAt() or equalTo() multiple times");
}
QueryParams newParams = params.endAt(node, childKey);
QueryParams newParams = isInclusive ? params.endAt(node, childKey) : params.endBefore(node, childKey);
validateLimit(newParams);
validateQueryEndpoints(newParams);
hardAssert(newParams.isValid());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ public final class QueryParams {

private static final String INDEX_START_VALUE = "sp";
private static final String INDEX_START_NAME = "sn";
private static final String INDEX_START_IS_INCLUSIVE = "sin";
private static final String INDEX_END_VALUE = "ep";
private static final String INDEX_END_NAME = "en";
private static final String INDEX_END_IS_INCLUSIVE = "ein";
private static final String LIMIT = "l";
private static final String VIEW_FROM = "vf";
private static final String INDEX = "i";
Expand All @@ -56,8 +58,10 @@ private static enum ViewFrom {
private ViewFrom viewFrom;
private Node indexStartValue = null;
private ChildKey indexStartName = null;
private boolean indexStartIsInclusive = true;
private Node indexEndValue = null;
private ChildKey indexEndName = null;
private boolean indexEndIsInclusive = true;

private Index index = PriorityIndex.getInstance();

Expand Down Expand Up @@ -85,6 +89,10 @@ public ChildKey getIndexStartName() {
}
}

public boolean getIndexStartIsInclusive() {
return indexStartIsInclusive;
}

public boolean hasEnd() {
return indexEndValue != null;
}
Expand All @@ -98,7 +106,7 @@ public Node getIndexEndValue() {

public ChildKey getIndexEndName() {
if (!hasEnd()) {
throw new IllegalArgumentException("Cannot get index end name if start has not been set");
throw new IllegalArgumentException("Cannot get index end name if end has not been set");
}
if (indexEndName != null) {
return indexEndName;
Expand All @@ -107,6 +115,10 @@ public ChildKey getIndexEndName() {
}
}

public boolean getIndexEndIsInclusive() {
return indexEndIsInclusive;
}

public boolean hasLimit() {
return limit != null;
}
Expand All @@ -131,8 +143,10 @@ private QueryParams copy() {
params.limit = limit;
params.indexStartValue = indexStartValue;
params.indexStartName = indexStartName;
params.indexStartIsInclusive = indexStartIsInclusive;
params.indexEndValue = indexEndValue;
params.indexEndName = indexEndName;
params.indexEndIsInclusive = indexEndIsInclusive;
params.viewFrom = viewFrom;
params.index = index;
return params;
Expand All @@ -152,26 +166,44 @@ public QueryParams limitToLast(int limit) {
return copy;
}

public QueryParams startAt(Node indexStartValue, ChildKey indexStartName) {
private QueryParams startAt(Node indexStartValue, ChildKey indexStartName, boolean indexStartIsInclusive) {
hardAssert(indexStartValue.isLeafNode() || indexStartValue.isEmpty());
// We can't tolerate longs as query endpoints. See comment in normalizeValue();
hardAssert(!(indexStartValue instanceof LongNode));
QueryParams copy = copy();
copy.indexStartValue = indexStartValue;
copy.indexStartName = indexStartName;
copy.indexStartIsInclusive = indexStartIsInclusive;
return copy;
}

public QueryParams endAt(Node indexEndValue, ChildKey indexEndName) {
public QueryParams startAt(Node indexStartValue, ChildKey indexStartName) {
return startAt(indexStartValue, indexStartName, true);
}

public QueryParams startAfter(Node indexStartValue, ChildKey indexStartName) {
return startAt(indexStartValue, indexStartName, false);
}

public QueryParams endAt(Node indexEndValue, ChildKey indexEndName, boolean indexEndIsInclusive) {
hardAssert(indexEndValue.isLeafNode() || indexEndValue.isEmpty());
// We can't tolerate longs as query endpoints. See comment in normalizeValue();
hardAssert(!(indexEndValue instanceof LongNode));
QueryParams copy = copy();
copy.indexEndValue = indexEndValue;
copy.indexEndName = indexEndName;
copy.indexEndIsInclusive = indexEndIsInclusive;
return copy;
}

public QueryParams endAt(Node indexEndValue, ChildKey indexEndName) {
return endAt(indexEndValue, indexEndName, true);
}

public QueryParams endBefore(Node indexEndValue, ChildKey indexEndName) {
return endAt(indexEndValue, indexEndName, false);
}

public QueryParams orderBy(Index index) {
QueryParams copy = copy();
copy.index = index;
Expand All @@ -190,12 +222,14 @@ public Map<String, Object> getWireProtocolParams() {
if (indexStartName != null) {
queryObject.put(INDEX_START_NAME, indexStartName.asString());
}
queryObject.put(INDEX_START_IS_INCLUSIVE, indexStartIsInclusive);
}
if (hasEnd()) {
queryObject.put(INDEX_END_VALUE, indexEndValue.getValue());
if (indexEndName != null) {
queryObject.put(INDEX_END_NAME, indexEndName.asString());
}
queryObject.put(INDEX_END_IS_INCLUSIVE, indexEndIsInclusive);
}
if (limit != null) {
queryObject.put(LIMIT, limit);
Expand Down Expand Up @@ -261,6 +295,7 @@ public static QueryParams fromQueryObject(Map<String, Object> map) {
if (indexStartName != null) {
params.indexStartName = ChildKey.fromString(indexStartName);
}
params.indexStartIsInclusive = (Boolean) map.get(INDEX_START_IS_INCLUSIVE);
}

if (map.containsKey(INDEX_END_VALUE)) {
Expand All @@ -270,6 +305,7 @@ public static QueryParams fromQueryObject(Map<String, Object> map) {
if (indexEndName != null) {
params.indexEndName = ChildKey.fromString(indexEndName);
}
params.indexEndIsInclusive = (Boolean) map.get(INDEX_END_IS_INCLUSIVE);
}

String viewFrom = (String) map.get(VIEW_FROM);
Expand Down Expand Up @@ -337,6 +373,12 @@ public boolean equals(Object o) {
: that.indexStartValue != null) {
return false;
}
if (indexStartIsInclusive != that.indexStartIsInclusive) {
return false;
}
if (indexEndIsInclusive != that.indexEndIsInclusive) {
return false;
}
// viewFrom might be null, but we really want to compare left vs right
if (isViewFromLeft() != that.isViewFromLeft()) {
return false;
Expand All @@ -351,8 +393,10 @@ public int hashCode() {
result = 31 * result + (isViewFromLeft() ? 1231 : 1237);
result = 31 * result + (indexStartValue != null ? indexStartValue.hashCode() : 0);
result = 31 * result + (indexStartName != null ? indexStartName.hashCode() : 0);
result = 31 * result + Boolean.valueOf(indexStartIsInclusive).hashCode();
result = 31 * result + (indexEndValue != null ? indexEndValue.hashCode() : 0);
result = 31 * result + (indexEndName != null ? indexEndName.hashCode() : 0);
result = 31 * result + Boolean.valueOf(indexEndIsInclusive).hashCode();
result = 31 * result + (index != null ? index.hashCode() : 0);
return result;
}
Expand Down
Loading