You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by xu...@apache.org on 2013/11/07 06:57:39 UTC

svn commit: r1539530 [1/4] - in /hive/trunk: common/src/java/org/apache/hadoop/hive/common/type/ common/src/java/org/apache/hive/common/util/ common/src/test/org/apache/hadoop/hive/common/type/ ql/src/java/org/apache/hadoop/hive/ql/exec/ ql/src/java/or...

Author: xuefu
Date: Thu Nov  7 05:57:37 2013
New Revision: 1539530

URL: http://svn.apache.org/r1539530
Log:
HIVE-5191: Add char data type (Jason via Xuefu)

Added:
    hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/HiveChar.java
    hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestHiveBaseChar.java
    hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestHiveChar.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFToChar.java
    hive/trunk/ql/src/test/queries/clientnegative/invalid_char_length_1.q
    hive/trunk/ql/src/test/queries/clientnegative/invalid_char_length_2.q
    hive/trunk/ql/src/test/queries/clientnegative/invalid_char_length_3.q
    hive/trunk/ql/src/test/queries/clientpositive/alter_char1.q
    hive/trunk/ql/src/test/queries/clientpositive/alter_char2.q
    hive/trunk/ql/src/test/queries/clientpositive/char_1.q
    hive/trunk/ql/src/test/queries/clientpositive/char_2.q
    hive/trunk/ql/src/test/queries/clientpositive/char_cast.q
    hive/trunk/ql/src/test/queries/clientpositive/char_comparison.q
    hive/trunk/ql/src/test/queries/clientpositive/char_join1.q
    hive/trunk/ql/src/test/queries/clientpositive/char_nested_types.q
    hive/trunk/ql/src/test/queries/clientpositive/char_udf1.q
    hive/trunk/ql/src/test/queries/clientpositive/char_union1.q
    hive/trunk/ql/src/test/queries/clientpositive/ctas_char.q
    hive/trunk/ql/src/test/results/clientnegative/invalid_char_length_1.q.out
    hive/trunk/ql/src/test/results/clientnegative/invalid_char_length_2.q.out
    hive/trunk/ql/src/test/results/clientnegative/invalid_char_length_3.q.out
    hive/trunk/ql/src/test/results/clientpositive/alter_char1.q.out
    hive/trunk/ql/src/test/results/clientpositive/alter_char2.q.out
    hive/trunk/ql/src/test/results/clientpositive/char_1.q.out
    hive/trunk/ql/src/test/results/clientpositive/char_2.q.out
    hive/trunk/ql/src/test/results/clientpositive/char_cast.q.out
    hive/trunk/ql/src/test/results/clientpositive/char_comparison.q.out
    hive/trunk/ql/src/test/results/clientpositive/char_join1.q.out
    hive/trunk/ql/src/test/results/clientpositive/char_nested_types.q.out
    hive/trunk/ql/src/test/results/clientpositive/char_udf1.q.out
    hive/trunk/ql/src/test/results/clientpositive/char_union1.q.out
    hive/trunk/ql/src/test/results/clientpositive/ctas_char.q.out
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/io/HiveBaseCharWritable.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/io/HiveCharWritable.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/lazy/LazyHiveChar.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/lazy/objectinspector/primitive/LazyHiveCharObjectInspector.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/lazybinary/LazyBinaryHiveChar.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/primitive/HiveCharObjectInspector.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/primitive/JavaHiveCharObjectInspector.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/primitive/SettableHiveCharObjectInspector.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/primitive/WritableConstantHiveCharObjectInspector.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/primitive/WritableHiveCharObjectInspector.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/typeinfo/BaseCharUtils.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/typeinfo/CharTypeInfo.java
    hive/trunk/serde/src/test/org/apache/hadoop/hive/serde2/io/TestHiveCharWritable.java
Removed:
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/typeinfo/VarcharUtils.java
Modified:
    hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/HiveBaseChar.java
    hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/HiveVarchar.java
    hive/trunk/common/src/java/org/apache/hive/common/util/HiveStringUtils.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveLexer.g
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/ParseUtils.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/TypeCheckProcFactory.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFComputeStats.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFConcat.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFLower.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFUpper.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFUtils.java
    hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/TestFunctionRegistry.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/SerDeUtils.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/binarysortable/BinarySortableSerDe.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/io/HiveVarcharWritable.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/lazy/LazyFactory.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/lazy/LazyUtils.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/lazy/objectinspector/primitive/LazyHiveVarcharObjectInspector.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/lazy/objectinspector/primitive/LazyPrimitiveObjectInspectorFactory.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/lazybinary/LazyBinaryFactory.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/lazybinary/LazyBinarySerDe.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/lazybinary/LazyBinaryUtils.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectInspectorConverters.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectInspectorUtils.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/PrimitiveObjectInspector.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/primitive/JavaHiveVarcharObjectInspector.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/primitive/PrimitiveObjectInspectorConverter.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/primitive/PrimitiveObjectInspectorFactory.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/primitive/PrimitiveObjectInspectorUtils.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/primitive/WritableHiveVarcharObjectInspector.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/typeinfo/TypeInfoFactory.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/typeinfo/TypeInfoUtils.java
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/typeinfo/VarcharTypeInfo.java
    hive/trunk/serde/src/test/org/apache/hadoop/hive/serde2/objectinspector/primitive/TestPrimitiveObjectInspectorFactory.java
    hive/trunk/serde/src/test/org/apache/hadoop/hive/serde2/typeinfo/TestTypeInfoUtils.java

Modified: hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/HiveBaseChar.java
URL: http://svn.apache.org/viewvc/hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/HiveBaseChar.java?rev=1539530&r1=1539529&r2=1539530&view=diff
==============================================================================
--- hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/HiveBaseChar.java (original)
+++ hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/HiveBaseChar.java Thu Nov  7 05:57:37 2013
@@ -21,7 +21,6 @@ import org.apache.commons.lang.StringUti
 
 public abstract class HiveBaseChar {
   protected String value;
-  protected int characterLength = -1;
 
   protected HiveBaseChar() {
   }
@@ -31,20 +30,11 @@ public abstract class HiveBaseChar {
    * @param val new value
    */
   public void setValue(String val, int maxLength) {
-    characterLength = -1;
     value = HiveBaseChar.enforceMaxLength(val, maxLength);
   }
 
   public void setValue(HiveBaseChar val, int maxLength) {
-    if ((maxLength < 0)
-        || (val.characterLength > 0 && val.characterLength <= maxLength)) {
-      // No length enforcement required, or source length is less than max length.
-      // We can copy the source value as-is.
-      value = val.value;
-      this.characterLength = val.characterLength;
-    } else {
-      setValue(val.value, maxLength);
-    }
+    setValue(val.value, maxLength);
   }
 
   public static String enforceMaxLength(String val, int maxLength) {
@@ -53,7 +43,7 @@ public abstract class HiveBaseChar {
     if (maxLength > 0) {
       int valLength = val.codePointCount(0, val.length());
       if (valLength > maxLength) {
-        // Truncate the excess trailing spaces to fit the character length.
+        // Truncate the excess chars to fit the character length.
         // Also make sure we take supplementary chars into account.
         value = val.substring(0, val.offsetByCodePoints(0, maxLength));
       }
@@ -61,14 +51,40 @@ public abstract class HiveBaseChar {
     return value;
   }
 
+  public static String getPaddedValue(String val, int maxLength) {
+    if (maxLength < 0) {
+      return val;
+    }
+
+    int valLength = val.codePointCount(0, val.length());
+    if (valLength > maxLength) {
+      return enforceMaxLength(val, maxLength);
+    }
+
+    if (maxLength > valLength) {
+      // Make sure we pad the right amount of spaces; valLength is in terms of code points,
+      // while StringUtils.rpad() is based on the number of java chars.
+      int padLength = val.length() + (maxLength - valLength);
+      val = StringUtils.rightPad(val, padLength);
+    }
+    return val;
+  }
+
   public String getValue() {
     return value;
   }
 
   public int getCharacterLength() {
-    if (characterLength < 0) {
-      characterLength = value.codePointCount(0, value.length());
-    }
-    return characterLength;
+    return value.codePointCount(0, value.length());
+  }
+
+  @Override
+  public int hashCode() {
+    return getValue().hashCode();
+  }
+
+  @Override
+  public String toString() {
+    return getValue();
   }
 }

Added: hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/HiveChar.java
URL: http://svn.apache.org/viewvc/hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/HiveChar.java?rev=1539530&view=auto
==============================================================================
--- hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/HiveChar.java (added)
+++ hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/HiveChar.java Thu Nov  7 05:57:37 2013
@@ -0,0 +1,91 @@
+/**
+ * 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.hadoop.hive.common.type;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * HiveChar.
+ * String values will be padded to full char length.
+ * Character legnth, comparison, hashCode should ignore trailing spaces.
+ */
+public class HiveChar extends HiveBaseChar
+  implements Comparable<HiveChar> {
+
+  public static final int MAX_CHAR_LENGTH = 255;
+
+  public HiveChar() {
+  }
+
+  public HiveChar(String val, int len) {
+    setValue(val, len);
+  }
+
+  public HiveChar(HiveChar hc, int len) {
+    setValue(hc.value, len);
+  }
+
+  /**
+   * Set char value, padding or truncating the value to the size of len parameter.
+   */
+  public void setValue(String val, int len) {
+    super.setValue(HiveBaseChar.getPaddedValue(val, len), -1);
+  }
+
+  public void setValue(String val) {
+    setValue(val, -1);
+  }
+
+  public String getStrippedValue() {
+    return StringUtils.stripEnd(value, " ");
+  }
+
+  protected String getPaddedValue() {
+    return value;
+  }
+
+  public int getCharacterLength() {
+    String strippedValue = getStrippedValue();
+    return strippedValue.codePointCount(0, strippedValue.length());
+  }
+
+  public String toString() {
+    return getPaddedValue();
+  }
+
+  public int compareTo(HiveChar rhs) {
+    if (rhs == this) {
+      return 0;
+    }
+    return this.getStrippedValue().compareTo(rhs.getStrippedValue());
+  }
+
+  public boolean equals(Object rhs) {
+    if (rhs == this) {
+      return true;
+    }
+    if (rhs == null || rhs.getClass() != getClass()) {
+      return false;
+    }
+    return this.getStrippedValue().equals(((HiveChar) rhs).getStrippedValue());
+  }
+
+  public int hashCode() {
+    return getStrippedValue().hashCode();
+  }
+}

Modified: hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/HiveVarchar.java
URL: http://svn.apache.org/viewvc/hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/HiveVarchar.java?rev=1539530&r1=1539529&r2=1539530&view=diff
==============================================================================
--- hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/HiveVarchar.java (original)
+++ hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/HiveVarchar.java Thu Nov  7 05:57:37 2013
@@ -51,11 +51,6 @@ public class HiveVarchar extends HiveBas
     super.setValue(hc.getValue(), -1);
   }
 
-  @Override
-  public String toString() {
-    return getValue();
-  }
-
   public int compareTo(HiveVarchar rhs) {
     if (rhs == this) {
       return 0;
@@ -69,9 +64,4 @@ public class HiveVarchar extends HiveBas
     }
     return this.getValue().equals(rhs.getValue());
   }
-
-  @Override
-  public int hashCode() {
-    return getValue().hashCode();
-  }
 }

Modified: hive/trunk/common/src/java/org/apache/hive/common/util/HiveStringUtils.java
URL: http://svn.apache.org/viewvc/hive/trunk/common/src/java/org/apache/hive/common/util/HiveStringUtils.java?rev=1539530&r1=1539529&r2=1539530&view=diff
==============================================================================
--- hive/trunk/common/src/java/org/apache/hive/common/util/HiveStringUtils.java (original)
+++ hive/trunk/common/src/java/org/apache/hive/common/util/HiveStringUtils.java Thu Nov  7 05:57:37 2013
@@ -39,6 +39,7 @@ import java.util.StringTokenizer;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hive.common.classification.InterfaceAudience;
 import org.apache.hadoop.hive.common.classification.InterfaceStability;
+import org.apache.hadoop.io.Text;
 
 /**
  * HiveStringUtils
@@ -807,4 +808,22 @@ public class HiveStringUtils {
     return sb.toString();
   }
 
+  /**
+   * Checks if b is the first byte of a UTF-8 character.
+   *
+   */
+  public static boolean isUtfStartByte(byte b) {
+    return (b & 0xC0) != 0x80;
+  }
+
+  public static int getTextUtfLength(Text t) {
+    byte[] data = t.getBytes();
+    int len = 0;
+    for (int i = 0; i < t.getLength(); i++) {
+      if (isUtfStartByte(data[i])) {
+        len++;
+      }
+    }
+    return len;
+  }
 }

Added: hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestHiveBaseChar.java
URL: http://svn.apache.org/viewvc/hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestHiveBaseChar.java?rev=1539530&view=auto
==============================================================================
--- hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestHiveBaseChar.java (added)
+++ hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestHiveBaseChar.java Thu Nov  7 05:57:37 2013
@@ -0,0 +1,82 @@
+package org.apache.hadoop.hive.common.type;
+
+import java.util.Random;
+
+import junit.framework.TestCase;
+
+public class TestHiveBaseChar extends TestCase {
+  static Random rnd = new Random();
+
+  public static int getRandomSupplementaryChar() {
+    int lowSurrogate = 0xDC00 + rnd.nextInt(1024);
+    //return 0xD8000000 + lowSurrogate;
+    int highSurrogate = 0xD800;
+    return Character.toCodePoint((char)highSurrogate, (char)lowSurrogate);
+  }
+
+  public static int getRandomCodePoint() {
+    int codePoint;
+    if (rnd.nextDouble() < 0.50) {
+      codePoint = 32 + rnd.nextInt(90);
+    } else {
+      codePoint = getRandomSupplementaryChar();
+    }
+    if (!Character.isValidCodePoint(codePoint)) {
+      System.out.println(Integer.toHexString(codePoint) + " is not a valid code point");
+    }
+    return codePoint;
+  }
+
+  public static int getRandomCodePoint(int excludeChar) {
+    while (true) {
+      int codePoint = getRandomCodePoint();
+      if (codePoint != excludeChar) {
+        return codePoint;
+      }
+    }
+  }
+
+  public static String createRandomSupplementaryCharString(int len) {
+    StringBuffer sb = new StringBuffer();
+    for (int idx = 0; idx < len; ++idx) {
+      sb.appendCodePoint(getRandomCodePoint(' '));
+    }
+    return sb.toString();
+  }
+
+  public void testStringLength() throws Exception {
+    int strLen = 20;
+    int[] lengths = { 15, 20, 25 };
+    // Try with supplementary characters
+    for (int idx1 = 0; idx1 < lengths.length; ++idx1) {
+      // Create random test string
+      int curLen = lengths[idx1];
+      String testString = createRandomSupplementaryCharString(curLen);
+      assertEquals(curLen, testString.codePointCount(0, testString.length()));
+      String enforcedString = HiveBaseChar.enforceMaxLength(testString, strLen);
+      if (curLen <= strLen) {
+        // No truncation needed
+        assertEquals(testString, enforcedString);
+      } else {
+        // String should have been truncated.
+        assertEquals(strLen, enforcedString.codePointCount(0, enforcedString.length()));
+      }
+    }
+  }
+
+  public void testGetPaddedValue() {
+    int strLen = 20;
+    int[] lengths = { 15, 20, 25 };
+    for (int idx1 = 0; idx1 < lengths.length; ++idx1) {
+      int curLen = lengths[idx1];
+      // Random test string
+      String testString = createRandomSupplementaryCharString(curLen);
+      assertEquals(curLen, testString.codePointCount(0, testString.length()));
+      String paddedString = HiveBaseChar.getPaddedValue(testString, strLen);
+      assertEquals(strLen, paddedString.codePointCount(0, paddedString.length()));
+    }
+
+    assertEquals("abc       ", HiveBaseChar.getPaddedValue("abc", 10));
+    assertEquals("abc       ", HiveBaseChar.getPaddedValue("abc ", 10));
+  }
+}

Added: hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestHiveChar.java
URL: http://svn.apache.org/viewvc/hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestHiveChar.java?rev=1539530&view=auto
==============================================================================
--- hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestHiveChar.java (added)
+++ hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestHiveChar.java Thu Nov  7 05:57:37 2013
@@ -0,0 +1,83 @@
+package org.apache.hadoop.hive.common.type;
+
+import junit.framework.TestCase;
+
+public class TestHiveChar extends TestCase {
+
+  public void testBasic() {
+    HiveChar hc = new HiveChar("abc", 10);
+    assertEquals("abc       ", hc.toString());
+    assertEquals("abc       ", hc.getPaddedValue());
+    assertEquals("abc", hc.getStrippedValue());
+    assertEquals(3, hc.getCharacterLength());
+
+    hc.setValue("abc123");
+    assertEquals("abc123", hc.toString());
+    assertEquals("abc123", hc.getPaddedValue());
+    assertEquals("abc123", hc.getStrippedValue());
+    assertEquals(6, hc.getCharacterLength());
+
+    hc.setValue("xyz", 15);
+    assertEquals("xyz            ", hc.toString());
+    assertEquals("xyz            ", hc.getPaddedValue());
+    assertEquals("xyz", hc.getStrippedValue());
+    assertEquals(3, hc.getCharacterLength());
+
+    hc.setValue("abc   ", 5);
+    assertEquals("abc  ", hc.toString());
+    assertEquals("abc", hc.getStrippedValue());
+    assertEquals(3, hc.getCharacterLength());
+  }
+
+  public void testStringLength() {
+    HiveChar hc = new HiveChar();
+
+    hc.setValue("0123456789", 5);
+    assertEquals("01234", hc.toString());
+
+    hc.setValue("0123456789", 10);
+    assertEquals("0123456789", hc.toString());
+
+    hc.setValue("0123456789", 15);
+    assertEquals("0123456789     ", hc.toString());
+  }
+
+  public void testComparison() {
+    HiveChar hc1 = new HiveChar();
+    HiveChar hc2 = new HiveChar();
+
+    // Identical strings
+    hc1.setValue("abc", 3);
+    hc2.setValue("abc", 3);
+    assertEquals(hc1, hc2);
+    assertEquals(hc2, hc1);
+    assertEquals(0, hc1.compareTo(hc2));
+    assertEquals(0, hc2.compareTo(hc1));
+
+    // Unequal strings
+    hc1.setValue("abc", 3);
+    hc1.setValue("123", 3);
+    assertFalse(hc1.equals(hc2));
+    assertFalse(hc2.equals(hc1));
+    assertFalse(0 == hc1.compareTo(hc2));
+    assertFalse(0 == hc2.compareTo(hc1));
+
+    // Trailing spaces are not significant
+    hc1.setValue("abc", 3);
+    hc2.setValue("abc", 5);
+    assertEquals("abc", hc1.toString());
+    assertEquals("abc  ", hc2.toString());
+    assertEquals(hc1, hc2);
+    assertEquals(hc2, hc1);
+    assertEquals(0, hc1.compareTo(hc2));
+    assertEquals(0, hc2.compareTo(hc1));
+
+    // Leading space is significant
+    hc1.setValue(" abc", 4);
+    hc2.setValue("abc", 4);
+    assertFalse(hc1.equals(hc2));
+    assertFalse(hc2.equals(hc1));
+    assertFalse(0 == hc1.compareTo(hc2));
+    assertFalse(0 == hc2.compareTo(hc1));
+  }
+}

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java?rev=1539530&r1=1539529&r2=1539530&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java Thu Nov  7 05:57:37 2013
@@ -359,6 +359,8 @@ public final class FunctionRegistry {
         GenericUDFToDecimal.class);
     registerGenericUDF(serdeConstants.VARCHAR_TYPE_NAME,
         GenericUDFToVarchar.class);
+    registerGenericUDF(serdeConstants.CHAR_TYPE_NAME,
+        GenericUDFToChar.class);
 
     // Aggregate functions
     registerGenericUDAF("max", new GenericUDAFMax());
@@ -656,9 +658,15 @@ public final class FunctionRegistry {
       PrimitiveTypeInfo a, PrimitiveTypeInfo b, PrimitiveCategory typeCategory) {
     // For types with parameters (like varchar), we need to determine the type parameters
     // that should be added to this type, based on the original 2 TypeInfos.
+    int maxLength;
     switch (typeCategory) {
+      case CHAR:
+        maxLength = getCommonLength(
+            TypeInfoUtils.getCharacterLengthForType(a),
+            TypeInfoUtils.getCharacterLengthForType(b));
+        return TypeInfoFactory.getCharTypeInfo(maxLength);
       case VARCHAR:
-        int maxLength = getCommonLength(
+        maxLength = getCommonLength(
             TypeInfoUtils.getCharacterLengthForType(a),
             TypeInfoUtils.getCharacterLengthForType(b));
         return TypeInfoFactory.getVarcharTypeInfo(maxLength);
@@ -1499,7 +1507,7 @@ public final class FunctionRegistry {
         udfClass == UDFToDouble.class || udfClass == UDFToFloat.class ||
         udfClass == UDFToInteger.class || udfClass == UDFToLong.class ||
         udfClass == UDFToShort.class || udfClass == UDFToString.class ||
-        udfClass == GenericUDFToVarchar.class ||
+        udfClass == GenericUDFToVarchar.class || udfClass == GenericUDFToChar.class ||
         udfClass == GenericUDFTimestamp.class || udfClass == GenericUDFToBinary.class ||
         udfClass == GenericUDFToDate.class  || udfClass == GenericUDFToDecimal.class;
   }

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java?rev=1539530&r1=1539529&r2=1539530&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java Thu Nov  7 05:57:37 2013
@@ -127,6 +127,10 @@ import org.apache.hadoop.hive.ql.securit
 import org.apache.hadoop.hive.ql.session.SessionState;
 import org.apache.hadoop.hive.serde.serdeConstants;
 import org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe;
+import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils;
+import org.apache.hadoop.hive.serde2.typeinfo.BaseCharTypeInfo;
+import org.apache.hadoop.hive.serde2.typeinfo.CharTypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.DecimalTypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.VarcharTypeInfo;
 import org.apache.hadoop.mapred.InputFormat;
@@ -150,6 +154,7 @@ public class DDLSemanticAnalyzer extends
     TokenToTypeName.put(HiveParser.TOK_FLOAT, serdeConstants.FLOAT_TYPE_NAME);
     TokenToTypeName.put(HiveParser.TOK_DOUBLE, serdeConstants.DOUBLE_TYPE_NAME);
     TokenToTypeName.put(HiveParser.TOK_STRING, serdeConstants.STRING_TYPE_NAME);
+    TokenToTypeName.put(HiveParser.TOK_CHAR, serdeConstants.CHAR_TYPE_NAME);
     TokenToTypeName.put(HiveParser.TOK_VARCHAR, serdeConstants.VARCHAR_TYPE_NAME);
     TokenToTypeName.put(HiveParser.TOK_BINARY, serdeConstants.BINARY_TYPE_NAME);
     TokenToTypeName.put(HiveParser.TOK_DATE, serdeConstants.DATE_TYPE_NAME);
@@ -168,6 +173,10 @@ public class DDLSemanticAnalyzer extends
     }
 
     switch (token) {
+    case HiveParser.TOK_CHAR:
+      CharTypeInfo charTypeInfo = ParseUtils.getCharTypeInfo(node);
+      typeName = charTypeInfo.getQualifiedName();
+      break;
     case HiveParser.TOK_VARCHAR:
       VarcharTypeInfo varcharTypeInfo = ParseUtils.getVarcharTypeInfo(node);
       typeName = varcharTypeInfo.getQualifiedName();

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveLexer.g
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveLexer.g?rev=1539530&r1=1539529&r2=1539530&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveLexer.g (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveLexer.g Thu Nov  7 05:57:37 2013
@@ -105,6 +105,7 @@ KW_DATETIME: 'DATETIME';
 KW_TIMESTAMP: 'TIMESTAMP';
 KW_DECIMAL: 'DECIMAL';
 KW_STRING: 'STRING';
+KW_CHAR: 'CHAR';
 KW_VARCHAR: 'VARCHAR';
 KW_ARRAY: 'ARRAY';
 KW_STRUCT: 'STRUCT';

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g?rev=1539530&r1=1539529&r2=1539530&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g Thu Nov  7 05:57:37 2013
@@ -110,6 +110,7 @@ TOK_DATELITERAL;
 TOK_DATETIME;
 TOK_TIMESTAMP;
 TOK_STRING;
+TOK_CHAR;
 TOK_VARCHAR;
 TOK_BINARY;
 TOK_DECIMAL;
@@ -1781,6 +1782,7 @@ primitiveType
     | KW_BINARY        ->    TOK_BINARY
     | KW_DECIMAL (LPAREN prec=Number (COMMA scale=Number)? RPAREN)? -> ^(TOK_DECIMAL $prec? $scale?)
     | KW_VARCHAR LPAREN length=Number RPAREN      ->    ^(TOK_VARCHAR $length)
+    | KW_CHAR LPAREN length=Number RPAREN      ->    ^(TOK_CHAR $length)
     ;
 
 listType

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/ParseUtils.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/ParseUtils.java?rev=1539530&r1=1539529&r2=1539530&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/ParseUtils.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/ParseUtils.java Thu Nov  7 05:57:37 2013
@@ -26,6 +26,9 @@ import org.apache.hadoop.hive.common.typ
 import org.apache.hadoop.hive.metastore.api.FieldSchema;
 import org.apache.hadoop.hive.ql.ErrorMsg;
 import org.apache.hadoop.hive.ql.plan.ExprNodeDesc;
+import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory;
+import org.apache.hadoop.hive.serde2.typeinfo.BaseCharTypeInfo;
+import org.apache.hadoop.hive.serde2.typeinfo.CharTypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.DecimalTypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.PrimitiveTypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
@@ -131,6 +134,16 @@ public final class ParseUtils {
     return TypeInfoFactory.getVarcharTypeInfo(Integer.valueOf(lengthStr));
   }
 
+  public static CharTypeInfo getCharTypeInfo(ASTNode node)
+      throws SemanticException {
+    if (node.getChildCount() != 1) {
+      throw new SemanticException("Bad params for type char");
+    }
+
+    String lengthStr = node.getChild(0).getText();
+    return TypeInfoFactory.getCharTypeInfo(Integer.valueOf(lengthStr));
+  }
+
   static int getIndex(String[] list, String elem) {
     for(int i=0; i < list.length; i++) {
       if (list[i].toLowerCase().equals(elem)) {

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/TypeCheckProcFactory.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/TypeCheckProcFactory.java?rev=1539530&r1=1539529&r2=1539530&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/TypeCheckProcFactory.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/TypeCheckProcFactory.java Thu Nov  7 05:57:37 2013
@@ -62,6 +62,8 @@ import org.apache.hadoop.hive.ql.udf.gen
 import org.apache.hadoop.hive.serde.serdeConstants;
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category;
+import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory;
+import org.apache.hadoop.hive.serde2.typeinfo.CharTypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.DecimalTypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.ListTypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.MapTypeInfo;
@@ -573,6 +575,8 @@ public final class TypeCheckProcFactory 
           serdeConstants.DOUBLE_TYPE_NAME);
       conversionFunctionTextHashMap.put(HiveParser.TOK_STRING,
           serdeConstants.STRING_TYPE_NAME);
+      conversionFunctionTextHashMap.put(HiveParser.TOK_CHAR,
+          serdeConstants.CHAR_TYPE_NAME);
       conversionFunctionTextHashMap.put(HiveParser.TOK_VARCHAR,
           serdeConstants.VARCHAR_TYPE_NAME);
       conversionFunctionTextHashMap.put(HiveParser.TOK_BINARY,
@@ -796,6 +800,13 @@ public final class TypeCheckProcFactory 
         if (isFunction) {
           ASTNode funcNameNode = (ASTNode)expr.getChild(0);
           switch (funcNameNode.getType()) {
+            case HiveParser.TOK_CHAR:
+              // Add type params
+              CharTypeInfo charTypeInfo = ParseUtils.getCharTypeInfo(funcNameNode);
+              if (genericUDF != null) {
+                ((SettableUDF)genericUDF).setTypeInfo(charTypeInfo);
+              }
+              break;
             case HiveParser.TOK_VARCHAR:
               VarcharTypeInfo varcharTypeInfo = ParseUtils.getVarcharTypeInfo(funcNameNode);
               if (genericUDF != null) {

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFComputeStats.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFComputeStats.java?rev=1539530&r1=1539529&r2=1539530&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFComputeStats.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFComputeStats.java Thu Nov  7 05:57:37 2013
@@ -83,6 +83,7 @@ public class GenericUDAFComputeStats ext
     case DOUBLE:
       return new GenericUDAFDoubleStatsEvaluator();
     case STRING:
+    case CHAR:
     case VARCHAR:
       return new GenericUDAFStringStatsEvaluator();
     case BINARY:

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFConcat.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFConcat.java?rev=1539530&r1=1539529&r2=1539530&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFConcat.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFConcat.java Thu Nov  7 05:57:37 2013
@@ -18,6 +18,7 @@
 
 package org.apache.hadoop.hive.ql.udf.generic;
 
+import org.apache.hadoop.hive.common.type.HiveChar;
 import org.apache.hadoop.hive.common.type.HiveVarchar;
 import org.apache.hadoop.hive.ql.exec.Description;
 import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
@@ -33,8 +34,8 @@ import org.apache.hadoop.hive.serde2.obj
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.BinaryObjectInspector;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorConverter.StringConverter;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
+import org.apache.hadoop.hive.serde2.typeinfo.BaseCharTypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
-import org.apache.hadoop.hive.serde2.typeinfo.VarcharTypeInfo;
 import org.apache.hadoop.io.BytesWritable;
 
 /**
@@ -62,7 +63,9 @@ public class GenericUDFConcat extends Ge
 
     // Loop through all the inputs to determine the appropriate return type/length.
     // Return type:
+    //  All CHAR inputs: return CHAR
     //  All VARCHAR inputs: return VARCHAR
+    //  All CHAR/VARCHAR inputs: return VARCHAR
     //  All BINARY inputs: return BINARY
     //  Otherwise return STRING
     argumentOIs = arguments;
@@ -88,10 +91,14 @@ public class GenericUDFConcat extends Ge
             returnType = PrimitiveCategory.STRING;
           }
           break;
+        case CHAR:
         case VARCHAR:
           if (!fixedLengthReturnValue) {
             returnType = PrimitiveCategory.STRING;
           }
+          if (fixedLengthReturnValue && currentCategory == PrimitiveCategory.VARCHAR) {
+            returnType = PrimitiveCategory.VARCHAR;
+          }
           break;
         default:
           returnType = PrimitiveCategory.STRING;
@@ -104,8 +111,10 @@ public class GenericUDFConcat extends Ge
       // max length for the char/varchar, then the return type reverts to string.
       if (fixedLengthReturnValue) {
         returnLength += GenericUDFUtils.StringHelper.getFixedStringSizeForType(poi);
-        if (returnType == PrimitiveCategory.VARCHAR
-            && returnLength > HiveVarchar.MAX_VARCHAR_LENGTH) {
+        if ((returnType == PrimitiveCategory.VARCHAR
+                && returnLength > HiveVarchar.MAX_VARCHAR_LENGTH)
+            || (returnType == PrimitiveCategory.CHAR
+                && returnLength > HiveChar.MAX_CHAR_LENGTH)) {
           returnType = PrimitiveCategory.STRING;
           fixedLengthReturnValue = false;
         }
@@ -119,11 +128,15 @@ public class GenericUDFConcat extends Ge
       // treat all inputs as string, the return value will be converted to the appropriate type.
       createStringConverters();
       returnHelper = new GenericUDFUtils.StringHelper(returnType);
+      BaseCharTypeInfo typeInfo;
       switch (returnType) {
         case STRING:
           return PrimitiveObjectInspectorFactory.writableStringObjectInspector;
+        case CHAR:
+          typeInfo = TypeInfoFactory.getCharTypeInfo(returnLength);
+          return PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(typeInfo);
         case VARCHAR:
-          VarcharTypeInfo typeInfo = TypeInfoFactory.getVarcharTypeInfo(returnLength);
+          typeInfo = TypeInfoFactory.getVarcharTypeInfo(returnLength);
           return PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(typeInfo);
         default:
           throw new UDFArgumentException("Unexpected CONCAT return type of " + returnType);

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFLower.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFLower.java?rev=1539530&r1=1539529&r2=1539530&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFLower.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFLower.java Thu Nov  7 05:57:37 2013
@@ -31,8 +31,8 @@ import org.apache.hadoop.hive.serde2.obj
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorConverter;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorConverter.StringConverter;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
+import org.apache.hadoop.hive.serde2.typeinfo.BaseCharTypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
-import org.apache.hadoop.hive.serde2.typeinfo.VarcharTypeInfo;
 
 /**
  * UDFLower.
@@ -65,11 +65,19 @@ public class GenericUDFLower extends Gen
     stringConverter = new PrimitiveObjectInspectorConverter.StringConverter(argumentOI);
     PrimitiveCategory inputType = argumentOI.getPrimitiveCategory();
     ObjectInspector outputOI = null;
+    BaseCharTypeInfo typeInfo;
     switch (inputType) {
+      case CHAR:
+        // return type should have same length as the input.
+        returnType = inputType;
+        typeInfo = TypeInfoFactory.getCharTypeInfo(
+            GenericUDFUtils.StringHelper.getFixedStringSizeForType(argumentOI));
+        outputOI = PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(typeInfo);
+        break;
       case VARCHAR:
         // return type should have same length as the input.
         returnType = inputType;
-        VarcharTypeInfo typeInfo = TypeInfoFactory.getVarcharTypeInfo(
+        typeInfo = TypeInfoFactory.getVarcharTypeInfo(
             GenericUDFUtils.StringHelper.getFixedStringSizeForType(argumentOI));
         outputOI = PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(typeInfo);
         break;

Added: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFToChar.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFToChar.java?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFToChar.java (added)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFToChar.java Thu Nov  7 05:57:37 2013
@@ -0,0 +1,113 @@
+/**
+ * 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.hadoop.hive.ql.udf.generic;
+
+import java.io.Serializable;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hive.ql.exec.Description;
+import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
+import org.apache.hadoop.hive.ql.metadata.HiveException;
+import org.apache.hadoop.hive.ql.udf.SettableUDF;
+import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorConverter.HiveCharConverter;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.SettableHiveCharObjectInspector;
+import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
+import org.apache.hadoop.hive.serde2.typeinfo.CharTypeInfo;
+
+@Description(name = "char",
+value = "CAST(<value> as CHAR(length)) - Converts the argument to a char value.",
+extended = "Values will be truncated if the input value is too long to fit"
++ " within the char length."
++ "Example:\n "
++ "  > SELECT CAST(1234 AS char(10)) FROM src LIMIT 1;\n"
++ "  '1234'")
+public class GenericUDFToChar extends GenericUDF implements SettableUDF, Serializable {
+  private static final Log LOG = LogFactory.getLog(GenericUDFToChar.class.getName());
+
+  private transient PrimitiveObjectInspector argumentOI;
+  private transient HiveCharConverter converter;
+
+  // The char type info need to be set prior to initialization,
+  // and must be preserved when the plan serialized to other processes.
+  private CharTypeInfo typeInfo;
+
+  public GenericUDFToChar() {
+  }
+
+  @Override
+  public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
+    if (arguments.length != 1) {
+      throw new UDFArgumentException("CHAR cast requires a value argument");
+    }
+    try {
+      argumentOI = (PrimitiveObjectInspector) arguments[0];
+    } catch (ClassCastException e) {
+      throw new UDFArgumentException(
+          "The function CHAR takes only primitive types");
+    }
+
+    // Check if this UDF has been provided with type params for the output char type
+    SettableHiveCharObjectInspector outputOI;
+    outputOI = (SettableHiveCharObjectInspector)
+          PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(typeInfo);
+
+    converter = new HiveCharConverter(argumentOI, outputOI);
+    return outputOI;
+  }
+
+  @Override
+  public Object evaluate(DeferredObject[] arguments) throws HiveException {
+      Object o0 = arguments[0].get();
+      if (o0 == null) {
+        return null;
+      }
+
+      return converter.convert(o0);
+  }
+
+  @Override
+  public String getDisplayString(String[] children) {
+    assert (children.length == 1);
+    StringBuilder sb = new StringBuilder();
+    sb.append("CAST( ");
+    sb.append(children[0]);
+    sb.append(" AS CHAR(");
+    sb.append("" + typeInfo.getLength());
+    sb.append(")");
+    return sb.toString();
+  }
+
+/**
+  * Provide char type parameters for the output object inspector.
+  * This should be done before the UDF is initialized.
+ */
+  @Override
+  public void setTypeInfo(TypeInfo typeInfo) throws UDFArgumentException {
+    this.typeInfo = (CharTypeInfo) typeInfo;
+  }
+
+  @Override
+  public TypeInfo getTypeInfo() {
+    return typeInfo;
+  }
+
+}

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFUpper.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFUpper.java?rev=1539530&r1=1539529&r2=1539530&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFUpper.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFUpper.java Thu Nov  7 05:57:37 2013
@@ -31,6 +31,7 @@ import org.apache.hadoop.hive.serde2.obj
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorConverter;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorConverter.StringConverter;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
+import org.apache.hadoop.hive.serde2.typeinfo.BaseCharTypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
 import org.apache.hadoop.hive.serde2.typeinfo.VarcharTypeInfo;
 
@@ -65,14 +66,23 @@ public class GenericUDFUpper extends Gen
     stringConverter = new PrimitiveObjectInspectorConverter.StringConverter(argumentOI);
     PrimitiveCategory inputType = argumentOI.getPrimitiveCategory();
     ObjectInspector outputOI = null;
+    BaseCharTypeInfo typeInfo;
     switch (inputType) {
+      case CHAR:
+        // return type should have same length as the input.
+        returnType = inputType;
+        typeInfo = TypeInfoFactory.getCharTypeInfo(
+            GenericUDFUtils.StringHelper.getFixedStringSizeForType(argumentOI));
+        outputOI = PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(
+            typeInfo);
+        break;
       case VARCHAR:
         // return type should have same length as the input.
         returnType = inputType;
-        VarcharTypeInfo varcharTypeInfo = TypeInfoFactory.getVarcharTypeInfo(
+        typeInfo = TypeInfoFactory.getVarcharTypeInfo(
             GenericUDFUtils.StringHelper.getFixedStringSizeForType(argumentOI));
         outputOI = PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(
-            varcharTypeInfo);
+            typeInfo);
         break;
       default:
         returnType = PrimitiveCategory.STRING;

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFUtils.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFUtils.java?rev=1539530&r1=1539529&r2=1539530&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFUtils.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFUtils.java Thu Nov  7 05:57:37 2013
@@ -29,6 +29,7 @@ import org.apache.hadoop.hive.ql.exec.Fu
 import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
 import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
 import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
+import org.apache.hadoop.hive.serde2.io.HiveCharWritable;
 import org.apache.hadoop.hive.serde2.io.HiveVarcharWritable;
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters;
@@ -41,9 +42,9 @@ import org.apache.hadoop.hive.serde2.obj
 import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
 import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.VoidObjectInspector;
+import org.apache.hadoop.hive.serde2.typeinfo.BaseCharTypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoUtils;
-import org.apache.hadoop.hive.serde2.typeinfo.VarcharTypeInfo;
 import org.apache.hadoop.io.Text;
 
 /**
@@ -367,6 +368,9 @@ public final class GenericUDFUtils {
         case STRING:
           returnValue = new Text();
           break;
+        case CHAR:
+          returnValue = new HiveCharWritable();
+          break;
         case VARCHAR:
           returnValue = new HiveVarcharWritable();
           break;
@@ -383,6 +387,9 @@ public final class GenericUDFUtils {
         case STRING:
           ((Text)returnValue).set(val);
           return returnValue;
+        case CHAR:
+          ((HiveCharWritable) returnValue).set(val);
+          return returnValue;
         case VARCHAR:
           ((HiveVarcharWritable)returnValue).set(val);
           return returnValue;
@@ -402,8 +409,9 @@ public final class GenericUDFUtils {
         throws UDFArgumentException {
       // TODO: we can support date, int, .. any types which would have a fixed length value
       switch (poi.getPrimitiveCategory()) {
+        case CHAR:
         case VARCHAR:
-          VarcharTypeInfo typeInfo = (VarcharTypeInfo) poi.getTypeInfo();
+          BaseCharTypeInfo typeInfo = (BaseCharTypeInfo) poi.getTypeInfo();
           return typeInfo.getLength();
         default:
           throw new UDFArgumentException("No fixed size for type " + poi.getTypeName());

Modified: hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/TestFunctionRegistry.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/TestFunctionRegistry.java?rev=1539530&r1=1539529&r2=1539530&view=diff
==============================================================================
--- hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/TestFunctionRegistry.java (original)
+++ hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/TestFunctionRegistry.java Thu Nov  7 05:57:37 2013
@@ -62,6 +62,8 @@ public class TestFunctionRegistry extend
   TypeInfo varchar5;
   TypeInfo varchar10;
   TypeInfo maxVarchar;
+  TypeInfo char5;
+  TypeInfo char10;
 
   @Override
   protected void setUp() {
@@ -69,6 +71,8 @@ public class TestFunctionRegistry extend
     maxVarchar = TypeInfoFactory.getPrimitiveTypeInfo(maxVarcharTypeName);
     varchar10 = TypeInfoFactory.getPrimitiveTypeInfo("varchar(10)");
     varchar5 = TypeInfoFactory.getPrimitiveTypeInfo("varchar(5)");
+    char10 = TypeInfoFactory.getPrimitiveTypeInfo("char(10)");
+    char5 = TypeInfoFactory.getPrimitiveTypeInfo("char(5)");
   }
 
   private void implicit(TypeInfo a, TypeInfo b, boolean convertible) {
@@ -95,6 +99,13 @@ public class TestFunctionRegistry extend
     implicit(TypeInfoFactory.stringTypeInfo, varchar20, true);
     implicit(varchar20, varchar10, true);
 
+    implicit(char10, TypeInfoFactory.stringTypeInfo, true);
+    implicit(TypeInfoFactory.stringTypeInfo, char10, true);
+    implicit(char5, char10, true);
+    implicit(char5, varchar10, true);
+    implicit(varchar5, char10, true);
+
+    implicit(TypeInfoFactory.intTypeInfo, char10, true);
     implicit(TypeInfoFactory.intTypeInfo, varchar10, true);
     implicit(TypeInfoFactory.intTypeInfo, TypeInfoFactory.stringTypeInfo, true);
   }
@@ -137,6 +148,8 @@ public class TestFunctionRegistry extend
 
     // String type affinity
     typeAffinity("typeaffinity1", TypeInfoFactory.stringTypeInfo, 1, Text.class);
+    typeAffinity("typeaffinity1", char5, 1, Text.class);
+    typeAffinity("typeaffinity1", varchar5, 1, Text.class);
 
     // Type affinity does not help when multiple methods have the same type affinity.
     typeAffinity("typeaffinity2", TypeInfoFactory.shortTypeInfo, 2, null);
@@ -191,8 +204,9 @@ public class TestFunctionRegistry extend
     verify(TestUDF.class, "one", TypeInfoFactory.intTypeInfo, TypeInfoFactory.intTypeInfo,
            IntWritable.class, IntWritable.class, false);
 
-    // Passing varchar arguments should prefer the version of evaluate() with Text args.
+    // Passing char/varchar arguments should prefer the version of evaluate() with Text args.
     verify(TestUDF.class, "same", varchar5, varchar10, Text.class, Text.class, false);
+    verify(TestUDF.class, "same", char5, char10, Text.class, Text.class, false);
 
     verify(TestUDF.class, "mismatch", TypeInfoFactory.voidTypeInfo, TypeInfoFactory.intTypeInfo,
            null, null, true);
@@ -214,6 +228,10 @@ public class TestFunctionRegistry extend
 
     common(TypeInfoFactory.stringTypeInfo, varchar10, TypeInfoFactory.stringTypeInfo);
     common(varchar10, TypeInfoFactory.stringTypeInfo, TypeInfoFactory.stringTypeInfo);
+    common(TypeInfoFactory.stringTypeInfo, char10, TypeInfoFactory.stringTypeInfo);
+    common(char10, TypeInfoFactory.stringTypeInfo, TypeInfoFactory.stringTypeInfo);
+    // common class between char/varchar is string?
+    common(char5, varchar10, TypeInfoFactory.stringTypeInfo);
   }
 
   private void comparison(TypeInfo a, TypeInfo b, TypeInfo result) {
@@ -238,6 +256,11 @@ public class TestFunctionRegistry extend
     comparison(TypeInfoFactory.stringTypeInfo, varchar10, TypeInfoFactory.stringTypeInfo);
     comparison(varchar10, TypeInfoFactory.stringTypeInfo, TypeInfoFactory.stringTypeInfo);
     comparison(varchar5, varchar10, varchar10);
+    comparison(TypeInfoFactory.stringTypeInfo, char10, TypeInfoFactory.stringTypeInfo);
+    comparison(char10, TypeInfoFactory.stringTypeInfo, TypeInfoFactory.stringTypeInfo);
+    comparison(char5, char10, char10);
+    // common comparison class for char/varchar is string?
+    comparison(char10, varchar5, TypeInfoFactory.stringTypeInfo);
   }
 
   /**
@@ -304,6 +327,14 @@ public class TestFunctionRegistry extend
     unionAll(varchar10, varchar5, varchar10);
     unionAll(varchar10, TypeInfoFactory.stringTypeInfo, TypeInfoFactory.stringTypeInfo);
     unionAll(TypeInfoFactory.stringTypeInfo, varchar10, TypeInfoFactory.stringTypeInfo);
+
+    unionAll(char5, char10, char10);
+    unionAll(char10, char5, char10);
+    unionAll(char10, TypeInfoFactory.stringTypeInfo, TypeInfoFactory.stringTypeInfo);
+    unionAll(TypeInfoFactory.stringTypeInfo, char10, TypeInfoFactory.stringTypeInfo);
+
+    // common class for char/varchar is string?
+    comparison(char10, varchar5, TypeInfoFactory.stringTypeInfo);
   }
 
   public void testGetTypeInfoForPrimitiveCategory() {
@@ -314,6 +345,14 @@ public class TestFunctionRegistry extend
     assertEquals(varchar10, FunctionRegistry.getTypeInfoForPrimitiveCategory(
         (PrimitiveTypeInfo) varchar10, (PrimitiveTypeInfo) varchar5, PrimitiveCategory.VARCHAR));
 
+    assertEquals(char10, FunctionRegistry.getTypeInfoForPrimitiveCategory(
+        (PrimitiveTypeInfo) char5, (PrimitiveTypeInfo) char10, PrimitiveCategory.CHAR));
+    assertEquals(char10, FunctionRegistry.getTypeInfoForPrimitiveCategory(
+        (PrimitiveTypeInfo) char10, (PrimitiveTypeInfo) char5, PrimitiveCategory.CHAR));
+
+    assertEquals(varchar10, FunctionRegistry.getTypeInfoForPrimitiveCategory(
+        (PrimitiveTypeInfo) varchar5, (PrimitiveTypeInfo) char10, PrimitiveCategory.VARCHAR));
+
     // non-qualified types should simply return the TypeInfo associated with that type
     assertEquals(TypeInfoFactory.stringTypeInfo, FunctionRegistry.getTypeInfoForPrimitiveCategory(
         (PrimitiveTypeInfo) varchar10, (PrimitiveTypeInfo) TypeInfoFactory.stringTypeInfo,

Added: hive/trunk/ql/src/test/queries/clientnegative/invalid_char_length_1.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientnegative/invalid_char_length_1.q?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientnegative/invalid_char_length_1.q (added)
+++ hive/trunk/ql/src/test/queries/clientnegative/invalid_char_length_1.q Thu Nov  7 05:57:37 2013
@@ -0,0 +1,2 @@
+drop table invalid_char_length_1;
+create table invalid_char_length_1 (c1 char(1000000));

Added: hive/trunk/ql/src/test/queries/clientnegative/invalid_char_length_2.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientnegative/invalid_char_length_2.q?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientnegative/invalid_char_length_2.q (added)
+++ hive/trunk/ql/src/test/queries/clientnegative/invalid_char_length_2.q Thu Nov  7 05:57:37 2013
@@ -0,0 +1 @@
+select cast(value as char(100000)) from src limit 1;

Added: hive/trunk/ql/src/test/queries/clientnegative/invalid_char_length_3.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientnegative/invalid_char_length_3.q?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientnegative/invalid_char_length_3.q (added)
+++ hive/trunk/ql/src/test/queries/clientnegative/invalid_char_length_3.q Thu Nov  7 05:57:37 2013
@@ -0,0 +1,3 @@
+drop table invalid_char_length_3;
+create table invalid_char_length_3 (c1 char(0));
+

Added: hive/trunk/ql/src/test/queries/clientpositive/alter_char1.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/alter_char1.q?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/alter_char1.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/alter_char1.q Thu Nov  7 05:57:37 2013
@@ -0,0 +1,32 @@
+drop table alter_char_1;
+
+create table alter_char_1 (key string, value string);
+insert overwrite table alter_char_1
+  select key, value from src order by key limit 5;
+
+select * from alter_char_1 order by key;
+
+-- change column to char
+alter table alter_char_1 change column value value char(20);
+-- contents should still look the same
+select * from alter_char_1 order by key;
+
+-- change column to smaller char
+alter table alter_char_1 change column value value char(3);
+-- value column should be truncated now
+select * from alter_char_1 order by key;
+
+-- change back to bigger char
+alter table alter_char_1 change column value value char(20);
+-- column values should be full size again
+select * from alter_char_1 order by key;
+
+-- add char column
+alter table alter_char_1 add columns (key2 int, value2 char(10));
+select * from alter_char_1 order by key;
+
+insert overwrite table alter_char_1
+  select key, value, key, value from src order by key limit 5;
+select * from alter_char_1 order by key;
+
+drop table alter_char_1;

Added: hive/trunk/ql/src/test/queries/clientpositive/alter_char2.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/alter_char2.q?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/alter_char2.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/alter_char2.q Thu Nov  7 05:57:37 2013
@@ -0,0 +1,22 @@
+
+-- alter column type, with partitioned table
+drop table if exists alter_char2;
+
+create table alter_char2 (
+  c1 char(255)
+) partitioned by (hr int);
+
+insert overwrite table alter_char2 partition (hr=1)
+  select value from src limit 1;
+
+select c1, length(c1) from alter_char2;
+
+alter table alter_char2 change column c1 c1 char(10);
+
+select hr, c1, length(c1) from alter_char2 where hr = 1;
+
+insert overwrite table alter_char2 partition (hr=2)
+  select key from src limit 1;
+
+select hr, c1, length(c1) from alter_char2 where hr = 1;
+select hr, c1, length(c1) from alter_char2 where hr = 2;

Added: hive/trunk/ql/src/test/queries/clientpositive/char_1.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/char_1.q?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/char_1.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/char_1.q Thu Nov  7 05:57:37 2013
@@ -0,0 +1,32 @@
+drop table char1;
+drop table char1_1;
+
+create table char1 (key char(10), value char(20));
+create table char1_1 (key string, value string);
+
+-- load from file
+load data local inpath '../../data/files/srcbucket0.txt' overwrite into table char1;
+select * from char1 order by key, value limit 2;
+
+-- insert overwrite, from same/different length char
+insert overwrite table char1
+  select cast(key as char(10)), cast(value as char(15)) from src order by key, value limit 2;
+select key, value from char1 order by key, value;
+
+-- insert overwrite, from string
+insert overwrite table char1
+  select key, value from src order by key, value limit 2;
+select key, value from char1 order by key, value;
+
+-- insert string from char
+insert overwrite table char1_1
+  select key, value from char1 order by key, value limit 2;
+select key, value from char1_1 order by key, value;
+
+-- respect string length
+insert overwrite table char1 
+  select key, cast(value as char(3)) from src order by key, value limit 2;
+select key, value from char1 order by key, value;
+
+drop table char1;
+drop table char1_1;

Added: hive/trunk/ql/src/test/queries/clientpositive/char_2.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/char_2.q?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/char_2.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/char_2.q Thu Nov  7 05:57:37 2013
@@ -0,0 +1,36 @@
+drop table char_2;
+
+create table char_2 (
+  key char(10),
+  value char(20)
+);
+
+insert overwrite table char_2 select * from src;
+
+select value, sum(cast(key as int)), count(*) numrows
+from src
+group by value
+order by value asc
+limit 5;
+
+-- should match the query from src
+select value, sum(cast(key as int)), count(*) numrows
+from char_2
+group by value
+order by value asc
+limit 5;
+
+select value, sum(cast(key as int)), count(*) numrows
+from src
+group by value
+order by value desc
+limit 5;
+
+-- should match the query from src
+select value, sum(cast(key as int)), count(*) numrows
+from char_2
+group by value
+order by value desc
+limit 5;
+
+drop table char_2;

Added: hive/trunk/ql/src/test/queries/clientpositive/char_cast.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/char_cast.q?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/char_cast.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/char_cast.q Thu Nov  7 05:57:37 2013
@@ -0,0 +1,92 @@
+
+-- Cast from char to other data types
+select
+  cast(cast('11' as string) as tinyint),
+  cast(cast('11' as string) as smallint),
+  cast(cast('11' as string) as int),
+  cast(cast('11' as string) as bigint),
+  cast(cast('11.00' as string) as float),
+  cast(cast('11.00' as string) as double),
+  cast(cast('11.00' as string) as decimal)
+from src limit 1;
+
+select
+  cast(cast('11' as char(10)) as tinyint),
+  cast(cast('11' as char(10)) as smallint),
+  cast(cast('11' as char(10)) as int),
+  cast(cast('11' as char(10)) as bigint),
+  cast(cast('11.00' as char(10)) as float),
+  cast(cast('11.00' as char(10)) as double),
+  cast(cast('11.00' as char(10)) as decimal)
+from src limit 1;
+
+select
+  cast(cast('2011-01-01' as string) as date),
+  cast(cast('2011-01-01 01:02:03' as string) as timestamp)
+from src limit 1;
+
+select
+  cast(cast('2011-01-01' as char(10)) as date),
+  cast(cast('2011-01-01 01:02:03' as char(30)) as timestamp)
+from src limit 1;
+
+-- no tests from string/char to boolean, that conversion doesn't look useful
+select
+  cast(cast('abc123' as string) as string),
+  cast(cast('abc123' as string) as varchar(10)),
+  cast(cast('abc123' as string) as char(10))
+from src limit 1;
+
+select
+  cast(cast('abc123' as char(10)) as string),
+  cast(cast('abc123' as char(10)) as varchar(10)),
+  cast(cast('abc123' as char(10)) as char(10))
+from src limit 1;
+
+select
+  cast(cast('abc123' as varchar(10)) as string),
+  cast(cast('abc123' as varchar(10)) as varchar(10)),
+  cast(cast('abc123' as varchar(10)) as char(10))
+from src limit 1;
+
+-- cast from other types to char
+select
+  cast(cast(11 as tinyint) as string),
+  cast(cast(11 as smallint) as string),
+  cast(cast(11 as int) as string),
+  cast(cast(11 as bigint) as string),
+  cast(cast(11.00 as float) as string),
+  cast(cast(11.00 as double) as string),
+  cast(cast(11.00 as decimal) as string)
+from src limit 1;
+
+select
+  cast(cast(11 as tinyint) as char(10)),
+  cast(cast(11 as smallint) as char(10)),
+  cast(cast(11 as int) as char(10)),
+  cast(cast(11 as bigint) as char(10)),
+  cast(cast(11.00 as float) as char(10)),
+  cast(cast(11.00 as double) as char(10)),
+  cast(cast(11.00 as decimal) as char(10))
+from src limit 1;
+
+select
+  cast(date '2011-01-01' as string),
+  cast(timestamp('2011-01-01 01:02:03') as string)
+from src limit 1;
+
+select
+  cast(date '2011-01-01' as char(10)),
+  cast(timestamp('2011-01-01 01:02:03') as char(30))
+from src limit 1;
+
+select
+  cast(true as string),
+  cast(false as string)
+from src limit 1;
+
+select
+  cast(true as char(10)),
+  cast(false as char(10))
+from src limit 1;
+

Added: hive/trunk/ql/src/test/queries/clientpositive/char_comparison.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/char_comparison.q?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/char_comparison.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/char_comparison.q Thu Nov  7 05:57:37 2013
@@ -0,0 +1,40 @@
+
+-- Should all be true
+select
+  cast('abc' as char(10)) =  cast('abc' as char(10)),
+  cast('abc' as char(10)) <= cast('abc' as char(10)),
+  cast('abc' as char(10)) >= cast('abc' as char(10)),
+  cast('abc' as char(10)) <  cast('abd' as char(10)),
+  cast('abc' as char(10)) >  cast('abb' as char(10)),
+  cast('abc' as char(10)) <> cast('abb' as char(10))
+from src limit 1;
+
+-- Different char lengths should still compare the same
+select
+  cast('abc' as char(10)) =  cast('abc' as char(3)),
+  cast('abc' as char(10)) <= cast('abc' as char(3)),
+  cast('abc' as char(10)) >= cast('abc' as char(3)),
+  cast('abc' as char(10)) <  cast('abd' as char(3)),
+  cast('abc' as char(10)) >  cast('abb' as char(3)),
+  cast('abc' as char(10)) <> cast('abb' as char(3))
+from src limit 1;
+
+-- Should work with string types as well
+select
+  cast('abc' as char(10)) =  'abc',
+  cast('abc' as char(10)) <= 'abc',
+  cast('abc' as char(10)) >= 'abc',
+  cast('abc' as char(10)) <  'abd',
+  cast('abc' as char(10)) >  'abb',
+  cast('abc' as char(10)) <> 'abb'
+from src limit 1;
+
+-- leading space is significant for char
+select
+  cast(' abc' as char(10)) <> cast('abc' as char(10))
+from src limit 1;
+
+-- trailing space is not significant for char
+select
+  cast('abc ' as char(10)) = cast('abc' as char(10))
+from src limit 1;

Added: hive/trunk/ql/src/test/queries/clientpositive/char_join1.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/char_join1.q?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/char_join1.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/char_join1.q Thu Nov  7 05:57:37 2013
@@ -0,0 +1,35 @@
+drop table char_join1_ch1;
+drop table char_join1_ch2;
+drop table char_join1_str;
+
+create table  char_join1_ch1 (
+  c1 int,
+  c2 char(10)
+);
+
+create table  char_join1_ch2 (
+  c1 int,
+  c2 char(20)
+);
+
+create table  char_join1_str (
+  c1 int,
+  c2 string
+);
+
+load data local inpath '../../data/files/vc1.txt' into table char_join1_ch1;
+load data local inpath '../../data/files/vc1.txt' into table char_join1_ch2;
+load data local inpath '../../data/files/vc1.txt' into table char_join1_str;
+
+-- Join char with same length char
+select * from char_join1_ch1 a join char_join1_ch1 b on (a.c2 = b.c2) order by a.c1;
+
+-- Join char with different length char
+select * from char_join1_ch1 a join char_join1_ch2 b on (a.c2 = b.c2) order by a.c1;
+
+-- Join char with string
+select * from char_join1_ch1 a join char_join1_str b on (a.c2 = b.c2) order by a.c1;
+
+drop table char_join1_ch1;
+drop table char_join1_ch2;
+drop table char_join1_str;

Added: hive/trunk/ql/src/test/queries/clientpositive/char_nested_types.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/char_nested_types.q?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/char_nested_types.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/char_nested_types.q Thu Nov  7 05:57:37 2013
@@ -0,0 +1,53 @@
+drop table char_nested_1;
+drop table char_nested_array;
+drop table char_nested_map;
+drop table char_nested_struct;
+drop table char_nested_cta;
+drop table char_nested_view;
+
+create table char_nested_1 (key int, value char(20));
+insert overwrite table char_nested_1
+  select key, value from src order by key limit 1;
+
+-- arrays
+create table char_nested_array (c1 array<char(20)>);
+insert overwrite table char_nested_array
+  select array(value, value) from char_nested_1;
+describe char_nested_array;
+select * from char_nested_array;
+
+-- maps
+create table char_nested_map (c1 map<int, char(20)>);
+insert overwrite table char_nested_map
+  select map(key, value) from char_nested_1;
+describe char_nested_map;
+select * from char_nested_map;
+
+-- structs
+create table char_nested_struct (c1 struct<a:int, b:char(20), c:string>);
+insert overwrite table char_nested_struct
+  select named_struct('a', key,
+                      'b', value,
+                      'c', cast(value as string))
+  from char_nested_1;
+describe char_nested_struct;
+select * from char_nested_struct;
+
+-- nested type with create table as
+create table char_nested_cta as 
+  select * from char_nested_struct;
+describe char_nested_cta;
+select * from char_nested_cta;
+
+-- nested type with view
+create table char_nested_view as 
+  select * from char_nested_struct;
+describe char_nested_view;
+select * from char_nested_view;
+
+drop table char_nested_1;
+drop table char_nested_array;
+drop table char_nested_map;
+drop table char_nested_struct;
+drop table char_nested_cta;
+drop table char_nested_view;

Added: hive/trunk/ql/src/test/queries/clientpositive/char_udf1.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/char_udf1.q?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/char_udf1.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/char_udf1.q Thu Nov  7 05:57:37 2013
@@ -0,0 +1,156 @@
+drop table char_udf_1;
+
+create table char_udf_1 (c1 string, c2 string, c3 char(10), c4 char(20));
+insert overwrite table char_udf_1
+  select key, value, key, value from src where key = '238' limit 1;
+
+-- UDFs with char support
+select 
+  concat(c1, c2),
+  concat(c3, c4),
+  concat(c1, c2) = concat(c3, c4)
+from char_udf_1 limit 1;
+
+select
+  upper(c2),
+  upper(c4),
+  upper(c2) = upper(c4)
+from char_udf_1 limit 1;
+
+select
+  lower(c2),
+  lower(c4),
+  lower(c2) = lower(c4)
+from char_udf_1 limit 1;
+
+-- Scalar UDFs
+select
+  ascii(c2),
+  ascii(c4),
+  ascii(c2) = ascii(c4)
+from char_udf_1 limit 1;
+
+select 
+  concat_ws('|', c1, c2),
+  concat_ws('|', c3, c4),
+  concat_ws('|', c1, c2) = concat_ws('|', c3, c4)
+from char_udf_1 limit 1;
+
+select
+  decode(encode(c2, 'US-ASCII'), 'US-ASCII'),
+  decode(encode(c4, 'US-ASCII'), 'US-ASCII'),
+  decode(encode(c2, 'US-ASCII'), 'US-ASCII') = decode(encode(c4, 'US-ASCII'), 'US-ASCII')
+from char_udf_1 limit 1;
+
+select
+  instr(c2, '_'),
+  instr(c4, '_'),
+  instr(c2, '_') = instr(c4, '_')
+from char_udf_1 limit 1;
+
+select
+  length(c2),
+  length(c4),
+  length(c2) = length(c4)
+from char_udf_1 limit 1;
+
+select
+  locate('a', 'abcdabcd', 3),
+  locate(cast('a' as char(1)), cast('abcdabcd' as char(10)), 3),
+  locate('a', 'abcdabcd', 3) = locate(cast('a' as char(1)), cast('abcdabcd' as char(10)), 3)
+from char_udf_1 limit 1;
+
+select
+  lpad(c2, 15, ' '),
+  lpad(c4, 15, ' '),
+  lpad(c2, 15, ' ') = lpad(c4, 15, ' ')
+from char_udf_1 limit 1;
+
+select
+  ltrim(c2),
+  ltrim(c4),
+  ltrim(c2) = ltrim(c4)
+from char_udf_1 limit 1;
+
+select
+  regexp(c2, 'val'),
+  regexp(c4, 'val'),
+  regexp(c2, 'val') = regexp(c4, 'val')
+from char_udf_1 limit 1;
+
+select
+  regexp_extract(c2, 'val_([0-9]+)', 1),
+  regexp_extract(c4, 'val_([0-9]+)', 1),
+  regexp_extract(c2, 'val_([0-9]+)', 1) = regexp_extract(c4, 'val_([0-9]+)', 1)
+from char_udf_1 limit 1;
+
+select
+  regexp_replace(c2, 'val', 'replaced'),
+  regexp_replace(c4, 'val', 'replaced'),
+  regexp_replace(c2, 'val', 'replaced') = regexp_replace(c4, 'val', 'replaced')
+from char_udf_1 limit 1;
+
+select
+  reverse(c2),
+  reverse(c4),
+  reverse(c2) = reverse(c4)
+from char_udf_1 limit 1;
+
+select
+  rpad(c2, 15, ' '),
+  rpad(c4, 15, ' '),
+  rpad(c2, 15, ' ') = rpad(c4, 15, ' ')
+from char_udf_1 limit 1;
+
+select
+  rtrim(c2),
+  rtrim(c4),
+  rtrim(c2) = rtrim(c4)
+from char_udf_1 limit 1;
+
+select
+  sentences('See spot run.  See jane run.'),
+  sentences(cast('See spot run.  See jane run.' as char(50)))
+from char_udf_1 limit 1;
+
+select
+  split(c2, '_'),
+  split(c4, '_')
+from char_udf_1 limit 1;
+
+select 
+  str_to_map('a:1,b:2,c:3',',',':'),
+  str_to_map(cast('a:1,b:2,c:3' as char(20)),',',':')
+from char_udf_1 limit 1;
+
+select
+  substr(c2, 1, 3),
+  substr(c4, 1, 3),
+  substr(c2, 1, 3) = substr(c4, 1, 3)
+from char_udf_1 limit 1;
+
+select
+  trim(c2),
+  trim(c4),
+  trim(c2) = trim(c4)
+from char_udf_1 limit 1;
+
+
+-- Aggregate Functions
+select
+  compute_stats(c2, 16),
+  compute_stats(c4, 16)
+from char_udf_1;
+
+select
+  min(c2),
+  min(c4)
+from char_udf_1;
+
+select
+  max(c2),
+  max(c4)
+from char_udf_1;
+
+
+drop table char_udf_1;

Added: hive/trunk/ql/src/test/queries/clientpositive/char_union1.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/char_union1.q?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/char_union1.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/char_union1.q Thu Nov  7 05:57:37 2013
@@ -0,0 +1,47 @@
+drop table char_union1_ch1;
+drop table char_union1_ch2;
+drop table char_union1_str;
+
+create table  char_union1_ch1 (
+  c1 int,
+  c2 char(10)
+);
+
+create table  char_union1_ch2 (
+  c1 int,
+  c2 char(20)
+);
+
+create table  char_union1_str (
+  c1 int,
+  c2 string
+);
+
+load data local inpath '../../data/files/vc1.txt' into table char_union1_ch1;
+load data local inpath '../../data/files/vc1.txt' into table char_union1_ch2;
+load data local inpath '../../data/files/vc1.txt' into table char_union1_str;
+
+-- union char with same length char
+select * from (
+  select * from char_union1_ch1
+  union all
+  select * from char_union1_ch1 limit 1
+) q1 sort by c1;
+
+-- union char with different length char
+select * from (
+  select * from char_union1_ch1
+  union all
+  select * from char_union1_ch2 limit 1
+) q1 sort by c1;
+
+-- union char with string
+select * from (
+  select * from char_union1_ch1
+  union all
+  select * from char_union1_str limit 1
+) q1 sort by c1;
+
+drop table char_union1_ch1;
+drop table char_union1_ch2;
+drop table char_union1_str;

Added: hive/trunk/ql/src/test/queries/clientpositive/ctas_char.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/ctas_char.q?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/ctas_char.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/ctas_char.q Thu Nov  7 05:57:37 2013
@@ -0,0 +1,22 @@
+drop table ctas_char_1;
+drop table ctas_char_2;
+drop view ctas_char_3;
+
+create table ctas_char_1 (key char(10), value string);
+insert overwrite table ctas_char_1 
+  select key, value from src sort by key, value limit 5;
+
+-- create table as with char column
+create table ctas_char_2 as select key, value from ctas_char_1;
+
+-- view with char column
+create view ctas_char_3 as select key, value from ctas_char_2;
+
+select key, value from ctas_char_1;
+select * from ctas_char_2;
+select * from ctas_char_3;
+
+
+drop table ctas_char_1;
+drop table ctas_char_2;
+drop view ctas_char_3;

Added: hive/trunk/ql/src/test/results/clientnegative/invalid_char_length_1.q.out
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/clientnegative/invalid_char_length_1.q.out?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/results/clientnegative/invalid_char_length_1.q.out (added)
+++ hive/trunk/ql/src/test/results/clientnegative/invalid_char_length_1.q.out Thu Nov  7 05:57:37 2013
@@ -0,0 +1,5 @@
+PREHOOK: query: drop table invalid_char_length_1
+PREHOOK: type: DROPTABLE
+POSTHOOK: query: drop table invalid_char_length_1
+POSTHOOK: type: DROPTABLE
+FAILED: RuntimeException Char length 1000000 out of allowed range [1, 255]

Added: hive/trunk/ql/src/test/results/clientnegative/invalid_char_length_2.q.out
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/clientnegative/invalid_char_length_2.q.out?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/results/clientnegative/invalid_char_length_2.q.out (added)
+++ hive/trunk/ql/src/test/results/clientnegative/invalid_char_length_2.q.out Thu Nov  7 05:57:37 2013
@@ -0,0 +1 @@
+FAILED: RuntimeException Char length 100000 out of allowed range [1, 255]

Added: hive/trunk/ql/src/test/results/clientnegative/invalid_char_length_3.q.out
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/clientnegative/invalid_char_length_3.q.out?rev=1539530&view=auto
==============================================================================
--- hive/trunk/ql/src/test/results/clientnegative/invalid_char_length_3.q.out (added)
+++ hive/trunk/ql/src/test/results/clientnegative/invalid_char_length_3.q.out Thu Nov  7 05:57:37 2013
@@ -0,0 +1,5 @@
+PREHOOK: query: drop table invalid_char_length_3
+PREHOOK: type: DROPTABLE
+POSTHOOK: query: drop table invalid_char_length_3
+POSTHOOK: type: DROPTABLE
+FAILED: RuntimeException Char length 0 out of allowed range [1, 255]