From 247b65d63e9864b7dee707dc5151e3972405472c Mon Sep 17 00:00:00 2001 From: Yuya Ebihara Date: Thu, 13 Feb 2025 08:51:01 +0900 Subject: [PATCH] Fix duplicate key due to non-lowercase collections in MongoDB --- .../io/trino/plugin/mongodb/MongoSession.java | 4 ++- .../mongodb/TestMongoConnectorTest.java | 35 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) 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 cbd592597d9d..a98045b15f0f 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 @@ -247,7 +247,9 @@ public Set getAllTables(String schema) .collect(toSet())); builder.addAll(getTableMetadataNames(schemaName)); - return builder.build(); + return builder.build().stream() + .map(name -> name.toLowerCase(ENGLISH)) + .collect(toImmutableSet()); } public MongoTable getTable(SchemaTableName tableName) 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 8131a8c28445..324cffb39163 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 @@ -57,6 +57,7 @@ import static io.trino.testing.TestingNames.randomNameSuffix; import static java.lang.String.format; import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Locale.ENGLISH; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assumptions.abort; @@ -149,6 +150,40 @@ public void testSortItemsReflectedInExplain() "TopNPartial\\[count = 5, orderBy = \\[nationkey DESC"); } + @Test + void testNonLowercaseCollection() + { + String suffix = randomNameSuffix(); + String schema = "test_db_" + suffix; + String table = "test_collection_" + suffix; + String mixedTable = "Test_Collection_" + suffix; + try { + MongoDatabase db = client.getDatabase(schema); + + db.createCollection(table); + db.getCollection(table).insertOne(new Document("lowercase", 1)); + + db.createCollection(mixedTable); + db.getCollection(mixedTable).insertOne(new Document("mixed", 2)); + + assertThatThrownBy(() -> client.getDatabase(schema.toUpperCase(ENGLISH)).createCollection(table)) + .hasMessageContaining("db already exists with different case"); + + db.createCollection(table.toUpperCase(ENGLISH)); + db.getCollection(table.toUpperCase(ENGLISH)).insertOne(new Document("uppercase", 3)); + + assertThat(query("SELECT * FROM information_schema.tables WHERE table_catalog = 'mongodb' AND table_schema = '" + schema + "'")) + .matches("VALUES (VARCHAR 'mongodb', VARCHAR '" + schema + "', VARCHAR '" + table + "', VARCHAR 'BASE TABLE')"); + assertThat(query("SELECT table_name, column_name FROM information_schema.columns WHERE table_catalog = 'mongodb' AND table_schema = '" + schema + "'")) + .matches("VALUES (VARCHAR '" + table + "', VARCHAR 'lowercase')"); + assertThat(query("SELECT * FROM " + schema + "." + table)) + .matches("VALUES BIGINT '1'"); + } + finally { + client.getDatabase(schema).drop(); + } + } + @Override protected Optional filterDataMappingSmokeTestData(DataMappingTestSetup dataMappingTestSetup) {