diff --git a/plugin/trino-mongodb/src/main/java/io/trino/plugin/mongodb/MongoSession.java b/plugin/trino-mongodb/src/main/java/io/trino/plugin/mongodb/MongoSession.java index e5c8d7723b3a..8f5a36924d8b 100644 --- a/plugin/trino-mongodb/src/main/java/io/trino/plugin/mongodb/MongoSession.java +++ b/plugin/trino-mongodb/src/main/java/io/trino/plugin/mongodb/MongoSession.java @@ -138,6 +138,8 @@ public class MongoSession private static final String FIELDS_TYPE_KEY = "type"; private static final String FIELDS_HIDDEN_KEY = "hidden"; + private static final Document EMPTY_DOCUMENT = new Document(); + private static final String AND_OP = "$and"; private static final String OR_OP = "$or"; @@ -587,16 +589,17 @@ static Document buildFilter(MongoTableHandle table) @VisibleForTesting static Document buildQuery(TupleDomain tupleDomain) { - Document query = new Document(); + ImmutableList.Builder queryBuilder = ImmutableList.builder(); if (tupleDomain.getDomains().isPresent()) { for (Map.Entry entry : tupleDomain.getDomains().get().entrySet()) { MongoColumnHandle column = (MongoColumnHandle) entry.getKey(); Optional predicate = buildPredicate(column, entry.getValue()); - predicate.ifPresent(query::putAll); + predicate.ifPresent(queryBuilder::add); } } - return query; + List query = queryBuilder.build(); + return query.isEmpty() ? EMPTY_DOCUMENT : andPredicate(query); } private static Optional buildPredicate(MongoColumnHandle column, Domain domain) diff --git a/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/TestMongoConnectorTest.java b/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/TestMongoConnectorTest.java index c8bf9d65cbdf..7291a08ca2cd 100644 --- a/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/TestMongoConnectorTest.java +++ b/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/TestMongoConnectorTest.java @@ -378,6 +378,20 @@ public void testPredicatePushdownCharWithPaddedSpace() } } + @Test + public void testPredicatePushdownMultipleNotEquals() + { + // Regression test for https://github.com/trinodb/trino/issues/19404 + try (TestTable table = new TestTable( + getQueryRunner()::execute, + "test_predicate_pushdown_with_multiple_not_equals", + "(id, value) AS VALUES (1, 10), (2, 20), (3, 30)")) { + assertThat(query("SELECT * FROM " + table.getName() + " WHERE id != 1 AND value != 20")) + .matches("VALUES (3, 30)") + .isFullyPushedDown(); + } + } + @Test public void testHighPrecisionDecimalPredicate() { diff --git a/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/TestMongoSession.java b/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/TestMongoSession.java index d0611b3f0acd..bfc497d769a7 100644 --- a/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/TestMongoSession.java +++ b/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/TestMongoSession.java @@ -86,8 +86,9 @@ public void testBuildQuery() Document query = MongoSession.buildQuery(tupleDomain); Document expected = new Document() - .append(COL1.getBaseName(), new Document().append("$gt", 100L).append("$lte", 200L)) - .append(COL2.getBaseName(), new Document("$eq", "a value")); + .append("$and", ImmutableList.of( + new Document(COL1.getBaseName(), new Document().append("$gt", 100L).append("$lte", 200L)), + new Document(COL2.getBaseName(), new Document("$eq", "a value")))); assertEquals(query, expected); } @@ -100,8 +101,9 @@ public void testBuildQueryStringType() Document query = MongoSession.buildQuery(tupleDomain); Document expected = new Document() - .append(COL3.getBaseName(), new Document().append("$gt", "hello").append("$lte", "world")) - .append(COL2.getBaseName(), new Document("$gte", "a value")); + .append("$and", ImmutableList.of( + new Document(COL3.getBaseName(), new Document().append("$gt", "hello").append("$lte", "world")), + new Document(COL2.getBaseName(), new Document("$gte", "a value")))); assertEquals(query, expected); } @@ -161,10 +163,11 @@ public void testBuildQueryNestedField() Document query = MongoSession.buildQuery(tupleDomain); Document expected = new Document() - .append("$or", asList( - new Document(COL5.getQualifiedName(), new Document("$gt", 200L)), - new Document(COL5.getQualifiedName(), new Document("$eq", null)))) - .append(COL6.getQualifiedName(), new Document("$eq", "a value")); + .append("$and", ImmutableList.of( + new Document("$or", asList( + new Document(COL5.getQualifiedName(), new Document("$gt", 200L)), + new Document(COL5.getQualifiedName(), new Document("$eq", null)))), + new Document(COL6.getQualifiedName(), new Document("$eq", "a value")))); assertEquals(query, expected); }