diff --git a/lance-spark-base_2.12/src/main/java/org/lance/spark/BaseLanceNamespaceSparkCatalog.java b/lance-spark-base_2.12/src/main/java/org/lance/spark/BaseLanceNamespaceSparkCatalog.java index 435e1b6eb..fd8daf8e8 100644 --- a/lance-spark-base_2.12/src/main/java/org/lance/spark/BaseLanceNamespaceSparkCatalog.java +++ b/lance-spark-base_2.12/src/main/java/org/lance/spark/BaseLanceNamespaceSparkCatalog.java @@ -234,7 +234,7 @@ public void initialize(String name, CaseInsensitiveStringMap options) { } // Initialize the namespace with proper configuration - Map namespaceOptions = new HashMap<>(options); + Map namespaceOptions = new HashMap<>(options.asCaseSensitiveMap()); // Save namespace impl and properties for serialization to workers this.namespaceImpl = impl; diff --git a/lance-spark-base_2.12/src/test/java/org/lance/spark/BaseLanceNamespaceSparkCatalogInitializeTest.java b/lance-spark-base_2.12/src/test/java/org/lance/spark/BaseLanceNamespaceSparkCatalogInitializeTest.java new file mode 100644 index 000000000..959915c65 --- /dev/null +++ b/lance-spark-base_2.12/src/test/java/org/lance/spark/BaseLanceNamespaceSparkCatalogInitializeTest.java @@ -0,0 +1,96 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.lance.spark; + +import org.lance.memwal.ShardingSpec; +import org.lance.spark.write.StagedCommit; + +import org.apache.spark.sql.types.StructType; +import org.apache.spark.sql.util.CaseInsensitiveStringMap; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class BaseLanceNamespaceSparkCatalogInitializeTest { + + @TempDir private Path tempDir; + + @Test + public void testInitializePreservesCaseSensitiveOptionKeys() { + Map rawOptions = new HashMap<>(); + rawOptions.put("impl", "dir"); + rawOptions.put("root", tempDir.toString()); + rawOptions.put("MyMixedCaseKey", "value1"); + rawOptions.put("ALLCAPS_KEY", "value2"); + rawOptions.put("camelCaseOption", "value3"); + + CaseInsensitiveStringMap options = new CaseInsensitiveStringMap(rawOptions); + + TestCatalog catalog = new TestCatalog(); + catalog.initialize("test", options); + + Map properties = catalog.getNamespaceProperties(); + + assertTrue( + properties.containsKey("MyMixedCaseKey"), + "Should preserve mixed-case key 'MyMixedCaseKey', got keys: " + properties.keySet()); + assertTrue( + properties.containsKey("ALLCAPS_KEY"), + "Should preserve all-caps key 'ALLCAPS_KEY', got keys: " + properties.keySet()); + assertTrue( + properties.containsKey("camelCaseOption"), + "Should preserve camelCase key 'camelCaseOption', got keys: " + properties.keySet()); + + assertEquals("value1", properties.get("MyMixedCaseKey")); + assertEquals("value2", properties.get("ALLCAPS_KEY")); + assertEquals("value3", properties.get("camelCaseOption")); + } + + private static class TestCatalog extends BaseLanceNamespaceSparkCatalog { + @Override + public LanceDataset createDataset( + LanceSparkReadOptions readOptions, + StructType sparkSchema, + Map initialStorageOptions, + String namespaceImpl, + Map namespaceProperties, + boolean managedVersioning, + String fileFormatVersion, + Map tableProperties, + ShardingSpec shardingSpec) { + return null; + } + + @Override + public LanceDataset createStagedDataset( + LanceSparkReadOptions readOptions, + StructType sparkSchema, + Map initialStorageOptions, + String namespaceImpl, + Map namespaceProperties, + boolean managedVersioning, + StagedCommit stagedCommit, + String fileFormatVersion, + Map tableProperties, + ShardingSpec shardingSpec) { + return null; + } + } +}