Skip to content
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

AllFilter with OR, bug fix #757

Merged
merged 7 commits into from
Jan 2, 2024
Merged
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 @@ -593,11 +593,11 @@ boolean canAddField() {
}

/** Filter for document where all values exists for an array */
public static class AllFilter extends SetFilterBase<String> {
private final Object arrayValue;
public static class AllFilter extends DBFilterBase {
private final List<Object> arrayValue;

public AllFilter(DocValueHasher hasher, String path, Object arrayValue) {
super("array_contains", path, getHashValue(hasher, path, arrayValue), Operator.CONTAINS);
public AllFilter(String path, List<Object> arrayValue) {
super(path);
this.arrayValue = arrayValue;
}

Expand All @@ -610,6 +610,23 @@ JsonNode asJson(JsonNodeFactory nodeFactory) {
boolean canAddField() {
return false;
}

public List<BuiltCondition> getAll() {
final ArrayList<BuiltCondition> result = new ArrayList<>();
for (Object value : arrayValue) {
result.add(
BuiltCondition.of(
DATA_CONTAINS,
Predicate.CONTAINS,
new JsonTerm(getHashValue(new DocValueHasher(), getPath(), value))));
}
return result;
}

@Override
public BuiltCondition get() {
throw new UnsupportedOperationException("For $all filter we always use getALL() method");
}
}

/** Filter for document where array has specified number of elements */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,12 @@ private static Expression<BuiltCondition> buildExpressionRecursive(
// second for loop, is to iterate all subComparisonExpression
for (ComparisonExpression comparisonExpression : logicalExpression.comparisonExpressions) {
for (DBFilterBase dbFilter : comparisonExpression.getDbFilters()) {
if (dbFilter instanceof DBFilterBase.InFilter inFilter) {
if (dbFilter instanceof DBFilterBase.AllFilter allFilter) {
List<BuiltCondition> allFilterConditions = allFilter.getAll();
List<Variable<BuiltCondition>> allFilterVariables =
allFilterConditions.stream().map(Variable::of).toList();
conditionExpressions.add(ExpressionUtils.andOf(allFilterVariables));
} else if (dbFilter instanceof DBFilterBase.InFilter inFilter) {
if (inFilter.operator.equals(DBFilterBase.InFilter.Operator.IN)) {
hasInFilterThisLevel = true;
} else if (inFilter.operator.equals(DBFilterBase.InFilter.Operator.NIN)) {
Expand Down Expand Up @@ -174,7 +179,6 @@ private static Expression<BuiltCondition> buildExpressionRecursive(
.get()));
return ExpressionUtils.buildExpression(
conditionExpressions, logicalExpression.getLogicalRelation().getOperator());
// return null;
}

// current logicalExpression is empty (implies sub-logicalExpression and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,8 @@ public static List<DBFilterBase> findDynamic(CaptureExpression captureExpression
}

if (captureExpression.marker() == ALL_GROUP) {
final DocValueHasher docValueHasher = new DocValueHasher();
List<Object> objects = (List<Object>) filterOperation.operand().value();
for (Object arrayValue : objects) {
filters.add(
new DBFilterBase.AllFilter(docValueHasher, captureExpression.path(), arrayValue));
}
List<Object> arrayValue = (List<Object>) filterOperation.operand().value();
filters.add(new DBFilterBase.AllFilter(captureExpression.path(), arrayValue));
}

if (captureExpression.marker() == SIZE_GROUP) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1090,19 +1090,84 @@ public void findWithAllFilter() throws Exception {

LogicalExpression implicitAnd = LogicalExpression.and();
implicitAnd.comparisonExpressions.add(new ComparisonExpression(null, null, null));
implicitAnd.comparisonExpressions.add(new ComparisonExpression(null, null, null));

List<DBFilterBase> filters1 =
List.of(new DBFilterBase.AllFilter(new DocValueHasher(), "tags", "tag1"));
List.of(new DBFilterBase.AllFilter("tags", List.of("tag1", "tag2")));
implicitAnd.comparisonExpressions.get(0).setDBFilters(filters1);
FindOperation operation =
FindOperation.unsortedSingle(
COMMAND_CONTEXT,
implicitAnd,
DocumentProjector.identityProjector(),
ReadType.DOCUMENT,
objectMapper);

Supplier<CommandResult> execute =
operation
.execute(queryExecutor)
.subscribe()
.withSubscriber(UniAssertSubscriber.create())
.awaitItem()
.getItem();

// assert query execution
assertThat(callCount.get()).isEqualTo(1);

// then result
CommandResult result = execute.get();
assertThat(result.data().getResponseDocuments())
.hasSize(1)
.containsOnly(objectMapper.readTree(doc1));
assertThat(result.status()).isNullOrEmpty();
assertThat(result.errors()).isNullOrEmpty();
}

@Test
public void findOrWithAllFilter() throws Exception {
String collectionReadCql =
"SELECT key, tx_id, doc_json FROM \"%s\".\"%s\" WHERE (array_contains CONTAINS ? OR (array_contains CONTAINS ? AND array_contains CONTAINS ?)) LIMIT 1"
.formatted(KEYSPACE_NAME, COLLECTION_NAME);

String doc1 =
"""
{
"_id": "doc1",
"username": "user1",
"registration_active" : true,
"tags": ["tag1", "tag2"]
}
""";

SimpleStatement stmt =
SimpleStatement.newInstance(
collectionReadCql, "username Suser1", "tags Stag1", "tags Stag2");
List<Row> rows = Arrays.asList(resultRow(0, "doc1", UUID.randomUUID(), doc1));
AsyncResultSet results = new MockAsyncResultSet(KEY_TXID_JSON_COLUMNS, rows, null);
final AtomicInteger callCount = new AtomicInteger();
QueryExecutor queryExecutor = mock(QueryExecutor.class);
when(queryExecutor.executeRead(eq(stmt), any(), anyInt()))
.then(
invocation -> {
callCount.incrementAndGet();
return Uni.createFrom().item(results);
});

LogicalExpression explicitOr = LogicalExpression.or();
explicitOr.comparisonExpressions.add(new ComparisonExpression(null, null, null));
explicitOr.comparisonExpressions.add(new ComparisonExpression(null, null, null));

List<DBFilterBase> filter1 =
List.of(
new DBFilterBase.TextFilter(
"username", DBFilterBase.MapFilterBase.Operator.EQ, "user1"));
explicitOr.comparisonExpressions.get(0).setDBFilters(filter1);
List<DBFilterBase> filters2 =
List.of(new DBFilterBase.AllFilter(new DocValueHasher(), "tags", "tag2"));
implicitAnd.comparisonExpressions.get(1).setDBFilters(filters2);
List.of(new DBFilterBase.AllFilter("tags", List.of("tag1", "tag2")));
explicitOr.comparisonExpressions.get(1).setDBFilters(filters2);

FindOperation operation =
FindOperation.unsortedSingle(
COMMAND_CONTEXT,
implicitAnd,
explicitOr,
DocumentProjector.identityProjector(),
ReadType.DOCUMENT,
objectMapper);
Expand Down Expand Up @@ -2396,15 +2461,9 @@ public void expressionSort() {
for (int i = 0; i < 20; i++) {
LogicalExpression implicitAnd1 = LogicalExpression.and();
implicitAnd1.comparisonExpressions.add(new ComparisonExpression(null, null, null));
implicitAnd1.comparisonExpressions.add(new ComparisonExpression(null, null, null));

List<DBFilterBase> filters1_1 =
List.of(new DBFilterBase.AllFilter(new DocValueHasher(), "tags", "tag1"));
implicitAnd1.comparisonExpressions.get(0).setDBFilters(filters1_1);
List<DBFilterBase> filters1_2 =
List.of(new DBFilterBase.AllFilter(new DocValueHasher(), "tags", "tag2"));
implicitAnd1.comparisonExpressions.get(1).setDBFilters(filters1_2);

List<DBFilterBase> filters1 =
List.of(new DBFilterBase.AllFilter("tags", List.of("tag1", "tag2")));
implicitAnd1.comparisonExpressions.get(0).setDBFilters(filters1);
FindOperation operation1 =
FindOperation.unsortedSingle(
COMMAND_CONTEXT,
Expand All @@ -2418,14 +2477,9 @@ public void expressionSort() {

LogicalExpression implicitAnd2 = LogicalExpression.and();
implicitAnd2.comparisonExpressions.add(new ComparisonExpression(null, null, null));
implicitAnd2.comparisonExpressions.add(new ComparisonExpression(null, null, null));

List<DBFilterBase> filters2_1 =
List.of(new DBFilterBase.AllFilter(new DocValueHasher(), "tags", "tag1"));
implicitAnd2.comparisonExpressions.get(0).setDBFilters(filters2_1);
List<DBFilterBase> filters2_2 =
List.of(new DBFilterBase.AllFilter(new DocValueHasher(), "tags", "tag2"));
implicitAnd2.comparisonExpressions.get(1).setDBFilters(filters2_2);
List<DBFilterBase> filters2 =
List.of(new DBFilterBase.AllFilter("tags", List.of("tag1", "tag2")));
implicitAnd2.comparisonExpressions.get(0).setDBFilters(filters2);

FindOperation operation2 =
FindOperation.unsortedSingle(
Expand Down