diff --git src/java/org/apache/hcatalog/data/schema/HCatSchema.java src/java/org/apache/hcatalog/data/schema/HCatSchema.java index fe6064e..b26e0bd 100644 --- src/java/org/apache/hcatalog/data/schema/HCatSchema.java +++ src/java/org/apache/hcatalog/data/schema/HCatSchema.java @@ -41,7 +41,8 @@ public class HCatSchema implements Serializable{ /** * * @param fieldSchemas is now owned by HCatSchema. Any subsequent modifications - * on fieldSchemas won't get reflected in HCatSchema. + * on fieldSchemas won't get reflected in HCatSchema. Each fieldSchema's name + * in the list must be unique. Otherwise throws IllegalArgumentException. */ public HCatSchema(final List fieldSchemas){ this.fieldSchemas = new ArrayList(fieldSchemas); @@ -49,8 +50,12 @@ public class HCatSchema implements Serializable{ fieldPositionMap = new HashMap(); fieldNames = new ArrayList(); for (HCatFieldSchema field : fieldSchemas){ - fieldPositionMap.put(field.getName(), idx); - fieldNames.add(field.getName()); + String fieldName = field.getName(); + if(fieldNames.contains(fieldName)) + throw new IllegalArgumentException("Field named " + fieldName + + " already exists"); + fieldPositionMap.put(fieldName, idx); + fieldNames.add(fieldName); idx++; } } @@ -60,9 +65,9 @@ public class HCatSchema implements Serializable{ if(hfs == null || fieldSchemas == null){ throw new HCatException("Attempt to append null HCatFieldSchema in HCatSchema."); } - //TODO Addition of existing field should not be allowed in Schema. - //Need to enforce that. For that to happen, field schema needs to implement Comparable. - // Also, HCatSchema needs to implement Comparable. + if(fieldNames.contains(hfs.getName())) + throw new HCatException("Attempt to append HCatFieldSchema with already " + + "existing name: " + hfs.fieldName + "."); this.fieldSchemas.add(hfs); String fieldName = hfs.getName(); diff --git src/test/org/apache/hcatalog/data/schema/TestHCatSchema.java src/test/org/apache/hcatalog/data/schema/TestHCatSchema.java new file mode 100644 index 0000000..3a72e78 --- /dev/null +++ src/test/org/apache/hcatalog/data/schema/TestHCatSchema.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.hcatalog.data.schema; + +import junit.framework.TestCase; +import org.apache.hcatalog.common.HCatException; +import org.apache.hcatalog.data.schema.HCatFieldSchema; +import org.apache.hcatalog.data.schema.HCatSchema; + +import java.util.ArrayList; +import java.util.List; + +public class TestHCatSchema extends TestCase { + public void testCannotAddFieldMoreThanOnce() throws HCatException { + List fieldSchemaList = new ArrayList(); + fieldSchemaList.add(new HCatFieldSchema("name", HCatFieldSchema.Type.STRING, "What's your handle?")); + fieldSchemaList.add(new HCatFieldSchema("age", HCatFieldSchema.Type.INT, "So very old")); + + HCatSchema schema = new HCatSchema(fieldSchemaList); + + assertTrue(schema.getFieldNames().contains("age")); + assertEquals(2, schema.getFields().size()); + + try { + schema.append(new HCatFieldSchema("age", HCatFieldSchema.Type.INT, "So very old")); + fail("Was able to append field schema with same name"); + } catch(HCatException he) { + assertTrue(he.getMessage().contains("Attempt to append HCatFieldSchema with already existing name: age.")); + } + + assertTrue(schema.getFieldNames().contains("age")); + assertEquals(2, schema.getFields().size()); + + // Should also not be able to add fields of different types with same name + try { + schema.append(new HCatFieldSchema("age", HCatFieldSchema.Type.STRING, "Maybe spelled out?")); + fail("Was able to append field schema with same name"); + } catch(HCatException he) { + assertTrue(he.getMessage().contains("Attempt to append HCatFieldSchema with already existing name: age.")); + } + + assertTrue(schema.getFieldNames().contains("age")); + assertEquals(2, schema.getFields().size()); + } + + public void testCannotInstantiateSchemaWithRepeatedFieldNames() throws HCatException { + List fieldSchemaList = new ArrayList(); + + fieldSchemaList.add(new HCatFieldSchema("memberID", HCatFieldSchema.Type.INT, "as a number")); + fieldSchemaList.add(new HCatFieldSchema("location", HCatFieldSchema.Type.STRING, "there's Waldo")); + + // No duplicate names. This should be ok + HCatSchema schema = new HCatSchema(fieldSchemaList); + + fieldSchemaList.add(new HCatFieldSchema("memberID", HCatFieldSchema.Type.STRING, "as a String")); + + // Now a duplicated field name. Should fail + try { + HCatSchema schema2 = new HCatSchema(fieldSchemaList); + fail("Able to add duplicate field name"); + } catch (IllegalArgumentException iae) { + assertTrue(iae.getMessage().contains("Field named memberID already exists")); + } + } +}