Skip to content

Commit e434dfa

Browse files
authored
feat: add support for date constant expression for mongo (#262)
1 parent 35fac78 commit e434dfa

File tree

10 files changed

+184
-0
lines changed

10 files changed

+184
-0
lines changed

document-store/src/integrationTest/java/org/hypertrace/core/documentstore/DocStoreQueryV1Test.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
import com.typesafe.config.ConfigFactory;
7070
import java.io.IOException;
7171
import java.util.ArrayList;
72+
import java.util.Date;
7273
import java.util.HashMap;
7374
import java.util.HashSet;
7475
import java.util.Iterator;
@@ -6546,6 +6547,58 @@ SELECT itemDetails.item, MAX(itemDetails.date) AS latest_date
65466547
dataStoreName, iterator, "query/sub_query_join_response_with_nested_fields.json", 3);
65476548
}
65486549

6550+
@ParameterizedTest
6551+
@ArgumentsSource(MongoProvider.class)
6552+
void testDateConstantExpressionInFilterForMongo(String dataStoreName) throws IOException {
6553+
Collection collection = getCollection(dataStoreName);
6554+
Date currentDate = new Date(System.currentTimeMillis());
6555+
6556+
// Test that DateConstantExpression works in a filter for Mongo
6557+
Query query =
6558+
Query.builder()
6559+
.setFilter(
6560+
RelationalExpression.of(
6561+
IdentifierExpression.of("_lastUpdateTime"),
6562+
LTE,
6563+
ConstantExpression.of(currentDate)))
6564+
.addSelection(IdentifierExpression.of("item"))
6565+
.addSelection(IdentifierExpression.of("price"))
6566+
.addSelection(IdentifierExpression.of("quantity"))
6567+
.addSort(IdentifierExpression.of("price"), ASC)
6568+
.addSort(IdentifierExpression.of("quantity"), DESC)
6569+
.build();
6570+
6571+
// Verify results
6572+
Iterator<Document> iterator = collection.aggregate(query);
6573+
assertDocsAndSizeEqual(
6574+
dataStoreName, iterator, "query/filter_contains_date_constant_expression.json", 8);
6575+
}
6576+
6577+
@ParameterizedTest
6578+
@ArgumentsSource(PostgresProvider.class)
6579+
void testDateConstantExpressionInFilterForPostgresThrowsException(String dataStoreName) {
6580+
Collection collection = getCollection(dataStoreName);
6581+
Date currentDate = new Date(System.currentTimeMillis());
6582+
6583+
// Test that DateConstantExpression throws UnsupportedOperationException in a filter for
6584+
// Postgres
6585+
Query query =
6586+
Query.builder()
6587+
.setFilter(
6588+
RelationalExpression.of(
6589+
IdentifierExpression.of("_lastUpdateTime"),
6590+
LTE,
6591+
ConstantExpression.of(currentDate)))
6592+
.addSelection(IdentifierExpression.of("item"))
6593+
.build();
6594+
6595+
// This should throw UnsupportedOperationException for Postgres
6596+
assertThrows(
6597+
UnsupportedOperationException.class,
6598+
() -> collection.aggregate(query),
6599+
"DateConstantExpression should throw UnsupportedOperationException for Postgres");
6600+
}
6601+
65496602
private static Collection getCollection(final String dataStoreName) {
65506603
return getCollection(dataStoreName, COLLECTION_NAME);
65516604
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
[
2+
{
3+
"item":"Shampoo",
4+
"price":5,
5+
"quantity":20
6+
},
7+
{
8+
"item":"Shampoo",
9+
"price":5,
10+
"quantity":10
11+
},
12+
{
13+
"item":"Comb",
14+
"price":7.5,
15+
"quantity":10
16+
},
17+
{
18+
"item":"Comb",
19+
"price":7.5,
20+
"quantity":5
21+
},
22+
{
23+
"item":"Soap",
24+
"price":10,
25+
"quantity":5
26+
},
27+
{
28+
"item":"Soap",
29+
"price":10,
30+
"quantity":2
31+
},
32+
{
33+
"item":"Soap",
34+
"price":20,
35+
"quantity":5
36+
},
37+
{
38+
"item":"Mirror",
39+
"price":20,
40+
"quantity":1
41+
}
42+
]

document-store/src/main/java/org/hypertrace/core/documentstore/expression/impl/ConstantExpression.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.hypertrace.core.documentstore.expression.impl;
22

3+
import java.util.Date;
34
import java.util.List;
45
import lombok.AccessLevel;
56
import lombok.AllArgsConstructor;
@@ -43,6 +44,10 @@ public static ConstantExpression of(final Document value) {
4344
return new DocumentConstantExpression(value);
4445
}
4546

47+
public static ConstantExpression of(final Date value) {
48+
return new DateConstantExpression(value);
49+
}
50+
4651
public static ConstantExpression ofStrings(final List<String> values) {
4752
return validateAndReturn(values);
4853
}
@@ -96,4 +101,25 @@ public String toString() {
96101
return "JSON(" + StringUtils.wrap(getValue().toJson(), "'") + ")";
97102
}
98103
}
104+
105+
public static class DateConstantExpression extends ConstantExpression {
106+
private DateConstantExpression(final Date value) {
107+
super(value);
108+
}
109+
110+
@Override
111+
public <T> T accept(final SelectTypeExpressionVisitor visitor) {
112+
return visitor.visit(this);
113+
}
114+
115+
@Override
116+
public Date getValue() {
117+
return (Date) value;
118+
}
119+
120+
@Override
121+
public String toString() {
122+
return "DATE(" + StringUtils.wrap(getValue().toString(), "'") + ")";
123+
}
124+
}
99125
}

document-store/src/main/java/org/hypertrace/core/documentstore/mongo/query/parser/MongoConstantExpressionParser.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.mongodb.BasicDBObject;
77
import lombok.NoArgsConstructor;
88
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression;
9+
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression.DateConstantExpression;
910
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression.DocumentConstantExpression;
1011

1112
@NoArgsConstructor
@@ -30,6 +31,12 @@ public Object visit(final DocumentConstantExpression expression) {
3031
}
3132
}
3233

34+
@SuppressWarnings("unchecked")
35+
@Override
36+
public Object visit(final DateConstantExpression expression) {
37+
return expression.getValue();
38+
}
39+
3340
Object parse(final ConstantExpression expression) {
3441
return expression.getValue();
3542
}

document-store/src/main/java/org/hypertrace/core/documentstore/mongo/query/parser/MongoNonProjectedSortTypeExpressionParser.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.hypertrace.core.documentstore.expression.impl.AggregateExpression;
1616
import org.hypertrace.core.documentstore.expression.impl.AliasedIdentifierExpression;
1717
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression;
18+
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression.DateConstantExpression;
1819
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression.DocumentConstantExpression;
1920
import org.hypertrace.core.documentstore.expression.impl.FunctionExpression;
2021
import org.hypertrace.core.documentstore.expression.impl.IdentifierExpression;
@@ -94,6 +95,16 @@ public Map<String, Object> visit(DocumentConstantExpression expression) {
9495
expression.getValue().toString()));
9596
}
9697

98+
@SuppressWarnings("unchecked")
99+
@Override
100+
public Map<String, Object> visit(DateConstantExpression expression) {
101+
throw new UnsupportedOperationException(
102+
String.format(
103+
"Cannot sort a constant expression ($%s) in MongoDB."
104+
+ "Set alias in selection and sort by the alias as identifier",
105+
expression.getValue().toString()));
106+
}
107+
97108
@SuppressWarnings("unchecked")
98109
@Override
99110
public Map<String, Object> visit(final AliasedIdentifierExpression expression) {

document-store/src/main/java/org/hypertrace/core/documentstore/mongo/query/parser/MongoProjectingParser.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.apache.commons.lang3.StringUtils;
99
import org.hypertrace.core.documentstore.expression.impl.AggregateExpression;
1010
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression;
11+
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression.DateConstantExpression;
1112
import org.hypertrace.core.documentstore.expression.impl.FunctionExpression;
1213
import org.hypertrace.core.documentstore.expression.impl.IdentifierExpression;
1314
import org.hypertrace.core.documentstore.expression.type.SelectTypeExpression;
@@ -51,6 +52,21 @@ public Map<String, Object> visit(final ConstantExpression expression) {
5152
return convertToMap(key, parsed);
5253
}
5354

55+
@SuppressWarnings("unchecked")
56+
@Override
57+
public Map<String, Object> visit(final DateConstantExpression expression) {
58+
final Object parsed;
59+
60+
try {
61+
parsed = baseParser.visit(expression);
62+
} catch (UnsupportedOperationException e) {
63+
return Map.of();
64+
}
65+
66+
final String key = getAlias(expression);
67+
return convertToMap(key, parsed);
68+
}
69+
5470
@SuppressWarnings("unchecked")
5571
@Override
5672
public Map<String, Object> visit(final FunctionExpression expression) {

document-store/src/main/java/org/hypertrace/core/documentstore/mongo/query/transformer/MongoSelectionsAddingTransformation.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.hypertrace.core.documentstore.expression.impl.AggregateExpression;
1111
import org.hypertrace.core.documentstore.expression.impl.AliasedIdentifierExpression;
1212
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression;
13+
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression.DateConstantExpression;
1314
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression.DocumentConstantExpression;
1415
import org.hypertrace.core.documentstore.expression.impl.FunctionExpression;
1516
import org.hypertrace.core.documentstore.expression.impl.IdentifierExpression;
@@ -113,6 +114,12 @@ public Optional<SelectionSpec> visit(final DocumentConstantExpression expression
113114
return Optional.empty();
114115
}
115116

117+
@SuppressWarnings("unchecked")
118+
@Override
119+
public Optional<SelectionSpec> visit(final DateConstantExpression expression) {
120+
return Optional.empty();
121+
}
122+
116123
@SuppressWarnings("unchecked")
117124
@Override
118125
public Optional<SelectionSpec> visit(final FunctionExpression expression) {

document-store/src/main/java/org/hypertrace/core/documentstore/mongo/query/transformer/MongoSelectionsUpdatingTransformation.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.hypertrace.core.documentstore.expression.impl.AggregateExpression;
1818
import org.hypertrace.core.documentstore.expression.impl.AliasedIdentifierExpression;
1919
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression;
20+
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression.DateConstantExpression;
2021
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression.DocumentConstantExpression;
2122
import org.hypertrace.core.documentstore.expression.impl.FunctionExpression;
2223
import org.hypertrace.core.documentstore.expression.impl.IdentifierExpression;
@@ -113,6 +114,12 @@ public SelectionSpec visit(final DocumentConstantExpression expression) {
113114
return source;
114115
}
115116

117+
@SuppressWarnings("unchecked")
118+
@Override
119+
public SelectionSpec visit(final DateConstantExpression expression) {
120+
return source;
121+
}
122+
116123
@SuppressWarnings("unchecked")
117124
@Override
118125
public SelectionSpec visit(final FunctionExpression expression) {

document-store/src/main/java/org/hypertrace/core/documentstore/parser/SelectTypeExpressionVisitor.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import org.hypertrace.core.documentstore.expression.impl.AliasedIdentifierExpression;
55
import org.hypertrace.core.documentstore.expression.impl.ArrayIdentifierExpression;
66
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression;
7+
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression.DateConstantExpression;
78
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression.DocumentConstantExpression;
89
import org.hypertrace.core.documentstore.expression.impl.FunctionExpression;
910
import org.hypertrace.core.documentstore.expression.impl.IdentifierExpression;
@@ -37,4 +38,12 @@ default <T> T visit(final ArrayIdentifierExpression expression) {
3738
default <T> T visit(final JsonIdentifierExpression expression) {
3839
return visit((IdentifierExpression) expression);
3940
}
41+
42+
/**
43+
* Visit a DateConstantExpression. Default implementation throws UnsupportedOperationException.
44+
* Override this method in implementations that support DateConstantExpression.
45+
*/
46+
default <T> T visit(final DateConstantExpression expression) {
47+
throw new UnsupportedOperationException("DateConstantExpression is not supported");
48+
}
4049
}

document-store/src/main/java/org/hypertrace/core/documentstore/postgres/query/v1/vistors/PostgresConstantExpressionVisitor.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import lombok.NoArgsConstructor;
44
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression;
5+
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression.DateConstantExpression;
56
import org.hypertrace.core.documentstore.expression.impl.ConstantExpression.DocumentConstantExpression;
67
import org.hypertrace.core.documentstore.postgres.query.v1.PostgresQueryParser;
78

@@ -30,4 +31,9 @@ public Object visit(final ConstantExpression expression) {
3031
public Object visit(final DocumentConstantExpression expression) {
3132
return expression.getValue();
3233
}
34+
35+
@Override
36+
public Object visit(final DateConstantExpression expression) {
37+
throw new UnsupportedOperationException("DateConstantExpression is not supported for Postgres");
38+
}
3339
}

0 commit comments

Comments
 (0)