http://git-wip-us.apache.org/repos/asf/kudu/blob/4f34b69d/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduClient.java
----------------------------------------------------------------------
diff --git 
a/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduClient.java 
b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduClient.java
index 1081cc6..f655222 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduClient.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduClient.java
@@ -31,6 +31,7 @@ import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.io.Closeable;
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -47,9 +48,11 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.kudu.ColumnSchema;
+import org.apache.kudu.ColumnTypeAttributes.ColumnTypeAttributesBuilder;
 import org.apache.kudu.Schema;
 import org.apache.kudu.Type;
 import org.apache.kudu.util.CapturingLogAppender;
+import org.apache.kudu.util.DecimalUtil;
 
 public class TestKuduClient extends BaseKuduTest {
   private static final Logger LOG = 
LoggerFactory.getLogger(TestKuduClient.class);
@@ -86,6 +89,21 @@ public class TestKuduClient extends BaseKuduTest {
     return new Schema(columns);
   }
 
+  private Schema createSchemaWithDecimalColumns() {
+    ArrayList<ColumnSchema> columns = new ArrayList<ColumnSchema>();
+    columns.add(new ColumnSchema.ColumnSchemaBuilder("key", 
Type.DECIMAL).key(true)
+        .typeAttributes(
+            new ColumnTypeAttributesBuilder()
+                
.precision(org.apache.kudu.util.DecimalUtil.MAX_DECIMAL64_PRECISION).build()
+        ).build());
+    columns.add(new ColumnSchema.ColumnSchemaBuilder("c1", 
Type.DECIMAL).nullable(true)
+        .typeAttributes(
+            new ColumnTypeAttributesBuilder()
+                
.precision(org.apache.kudu.util.DecimalUtil.MAX_DECIMAL128_PRECISION).build()
+        ).build());
+    return new Schema(columns);
+  }
+
   private static CreateTableOptions createTableOptions() {
     return new 
CreateTableOptions().setRangePartitionColumns(ImmutableList.of("key"));
   }
@@ -426,6 +444,48 @@ public class TestKuduClient extends BaseKuduTest {
   }
 
   /**
+   * Test inserting and retrieving decimal columns.
+   */
+  @Test(timeout = 100000)
+  public void testDecimalColumns() throws Exception {
+    Schema schema = createSchemaWithDecimalColumns();
+    syncClient.createTable(tableName, schema, createTableOptions());
+
+    List<Long> timestamps = new ArrayList<>();
+
+    KuduSession session = syncClient.newSession();
+    KuduTable table = syncClient.openTable(tableName);
+
+    // Verify ColumnTypeAttributes
+    assertEquals(DecimalUtil.MAX_DECIMAL128_PRECISION,
+        table.getSchema().getColumn("c1").getTypeAttributes().getPrecision());
+
+    for (int i = 0; i < 9; i++) {
+      Insert insert = table.newInsert();
+      PartialRow row = insert.getRow();
+      row.addDecimal("key", BigDecimal.valueOf(i));
+      if (i % 2 == 1) {
+        row.addDecimal("c1", BigDecimal.valueOf(i));
+      }
+      session.apply(insert);
+    }
+    session.flush();
+
+    List<String> rowStrings = scanTableToStrings(table);
+    assertEquals(9, rowStrings.size());
+    for (int i = 0; i < rowStrings.size(); i++) {
+      StringBuilder expectedRow = new StringBuilder();
+      expectedRow.append(String.format("DECIMAL key(18, 0)=%s, DECIMAL c1(38, 
0)=", String.valueOf(i)));
+      if (i % 2 == 1) {
+        expectedRow.append(String.valueOf(i));
+      } else {
+        expectedRow.append("NULL");
+      }
+      assertEquals(expectedRow.toString(), rowStrings.get(i));
+    }
+  }
+
+  /**
    * Test scanning with predicates.
    */
   @Test

http://git-wip-us.apache.org/repos/asf/kudu/blob/4f34b69d/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java
----------------------------------------------------------------------
diff --git 
a/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java 
b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java
index d192be8..e7c40c0 100644
--- 
a/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java
+++ 
b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java
@@ -24,6 +24,7 @@ import static 
org.apache.kudu.client.KuduPredicate.ComparisonOp.LESS;
 import static org.apache.kudu.client.KuduPredicate.ComparisonOp.LESS_EQUAL;
 import static org.apache.kudu.client.KuduPredicate.PredicateType.RANGE;
 
+import java.math.BigDecimal;
 import java.util.Arrays;
 
 import com.google.common.base.Preconditions;
@@ -33,6 +34,7 @@ import org.junit.Test;
 
 import org.apache.kudu.ColumnSchema;
 import org.apache.kudu.Type;
+import org.apache.kudu.util.DecimalUtil;
 
 public class TestKuduPredicate {
 
@@ -63,6 +65,21 @@ public class TestKuduPredicate {
   private static final ColumnSchema binaryCol =
       new ColumnSchema.ColumnSchemaBuilder("binary", Type.BINARY).build();
 
+  private static final ColumnSchema decimal32Col =
+      new ColumnSchema.ColumnSchemaBuilder("decimal32", Type.DECIMAL)
+          
.typeAttributes(DecimalUtil.typeAttributes(DecimalUtil.MAX_DECIMAL32_PRECISION, 
2))
+          .build();
+
+  private static final ColumnSchema decimal64Col =
+      new ColumnSchema.ColumnSchemaBuilder("decimal64", Type.DECIMAL)
+          
.typeAttributes(DecimalUtil.typeAttributes(DecimalUtil.MAX_DECIMAL64_PRECISION, 
2))
+          .build();
+
+  private static final ColumnSchema decimal128Col =
+      new ColumnSchema.ColumnSchemaBuilder("decimal128", Type.DECIMAL)
+          
.typeAttributes(DecimalUtil.typeAttributes(DecimalUtil.MAX_DECIMAL128_PRECISION,
 2))
+          .build();
+
   private static KuduPredicate intRange(int lower, int upper) {
     Preconditions.checkArgument(lower < upper);
     return new KuduPredicate(RANGE, intCol, Bytes.fromInt(lower), 
Bytes.fromInt(upper));
@@ -844,6 +861,66 @@ public class TestKuduPredicate {
               KuduPredicate.newInListPredicate(doubleCol, 
ImmutableList.of(14d, 18d, 20d)),
               KuduPredicate.newInListPredicate(doubleCol, 
ImmutableList.of(14d, 18d)));
 
+    testMerge(KuduPredicate.newComparisonPredicate(decimal32Col, GREATER_EQUAL,
+        BigDecimal.valueOf(12345, 2)),
+        KuduPredicate.newComparisonPredicate(decimal32Col, LESS,
+            BigDecimal.valueOf(67890,2)),
+        new KuduPredicate(RANGE,
+            decimal32Col,
+            Bytes.fromBigDecimal(BigDecimal.valueOf(12345, 2),
+                DecimalUtil.MAX_DECIMAL32_PRECISION),
+            Bytes.fromBigDecimal(BigDecimal.valueOf(67890, 2),
+                DecimalUtil.MAX_DECIMAL32_PRECISION)));
+
+    testMerge(KuduPredicate.newInListPredicate(decimal32Col, ImmutableList.of(
+            BigDecimal.valueOf(12345, 2),
+            BigDecimal.valueOf(45678, 2))),
+        KuduPredicate.newInListPredicate(decimal32Col, ImmutableList.of(
+            BigDecimal.valueOf(45678, 2),
+            BigDecimal.valueOf(98765, 2))),
+        KuduPredicate.newInListPredicate(decimal32Col, ImmutableList.of(
+            BigDecimal.valueOf(45678, 2))));
+
+    testMerge(KuduPredicate.newInListPredicate(decimal64Col, ImmutableList.of(
+        BigDecimal.valueOf(12345678910L, 2),
+        BigDecimal.valueOf(34567891011L, 2))),
+        KuduPredicate.newInListPredicate(decimal64Col, ImmutableList.of(
+            BigDecimal.valueOf(34567891011L, 2),
+            BigDecimal.valueOf(98765432111L, 2))),
+        KuduPredicate.newInListPredicate(decimal64Col, ImmutableList.of(
+            BigDecimal.valueOf(34567891011L, 2))));
+
+    testMerge(KuduPredicate.newComparisonPredicate(decimal64Col, GREATER_EQUAL,
+        BigDecimal.valueOf(12345678910L, 2)),
+        KuduPredicate.newComparisonPredicate(decimal64Col, LESS,
+            BigDecimal.valueOf(67890101112L,2)),
+        new KuduPredicate(RANGE,
+            decimal64Col,
+            Bytes.fromBigDecimal(BigDecimal.valueOf(12345678910L, 2),
+                DecimalUtil.MAX_DECIMAL64_PRECISION),
+            Bytes.fromBigDecimal(BigDecimal.valueOf(67890101112L, 2),
+                DecimalUtil.MAX_DECIMAL64_PRECISION)));
+
+    testMerge(KuduPredicate.newInListPredicate(decimal128Col, ImmutableList.of(
+        new BigDecimal("1234567891011121314.15"),
+        new BigDecimal("3456789101112131415.16"))),
+        KuduPredicate.newInListPredicate(decimal128Col, ImmutableList.of(
+            new BigDecimal("3456789101112131415.16"),
+            new BigDecimal("9876543212345678910.11"))),
+        KuduPredicate.newInListPredicate(decimal128Col, ImmutableList.of(
+            new BigDecimal("3456789101112131415.16"))));
+
+    testMerge(KuduPredicate.newComparisonPredicate(decimal128Col, 
GREATER_EQUAL,
+        new BigDecimal("1234567891011121314.15")),
+        KuduPredicate.newComparisonPredicate(decimal128Col, LESS,
+            new BigDecimal("67891011121314151617.18")),
+        new KuduPredicate(RANGE,
+            decimal128Col,
+            Bytes.fromBigDecimal(new BigDecimal("1234567891011121314.15"),
+                DecimalUtil.MAX_DECIMAL128_PRECISION),
+            Bytes.fromBigDecimal(new BigDecimal("67891011121314151617.18"),
+                DecimalUtil.MAX_DECIMAL128_PRECISION)));
+
     testMerge(KuduPredicate.newComparisonPredicate(binaryCol, GREATER_EQUAL,
                                                    new byte[] { 0, 1, 2, 3, 4, 
5, 6 }),
               KuduPredicate.newComparisonPredicate(binaryCol, LESS, new byte[] 
{ 10 }),
@@ -871,11 +948,13 @@ public class TestKuduPredicate {
                         KuduPredicate.newComparisonPredicate(floatCol, LESS, 
Math.nextAfter(12.345f, Float.POSITIVE_INFINITY)));
     Assert.assertEquals(KuduPredicate.newComparisonPredicate(doubleCol, 
LESS_EQUAL, 12.345),
                         KuduPredicate.newComparisonPredicate(doubleCol, LESS, 
Math.nextAfter(12.345, Float.POSITIVE_INFINITY)));
+    Assert.assertEquals(
+        KuduPredicate.newComparisonPredicate(decimal32Col, LESS_EQUAL, 
BigDecimal.valueOf(12345,2)),
+        KuduPredicate.newComparisonPredicate(decimal32Col, LESS, 
BigDecimal.valueOf(12346,2)));
     Assert.assertEquals(KuduPredicate.newComparisonPredicate(stringCol, 
LESS_EQUAL, "a"),
                         KuduPredicate.newComparisonPredicate(stringCol, LESS, 
"a\0"));
     Assert.assertEquals(KuduPredicate.newComparisonPredicate(binaryCol, 
LESS_EQUAL, new byte[] { (byte) 10 }),
                         KuduPredicate.newComparisonPredicate(binaryCol, LESS, 
new byte[] { (byte) 10, (byte) 0 }));
-
     Assert.assertEquals(KuduPredicate.newComparisonPredicate(byteCol, 
LESS_EQUAL, Byte.MAX_VALUE),
                         KuduPredicate.newIsNotNullPredicate(byteCol));
     Assert.assertEquals(KuduPredicate.newComparisonPredicate(shortCol, 
LESS_EQUAL, Short.MAX_VALUE),
@@ -908,6 +987,9 @@ public class TestKuduPredicate {
                         KuduPredicate.newComparisonPredicate(floatCol, 
GREATER, 12.345f));
     Assert.assertEquals(KuduPredicate.newComparisonPredicate(doubleCol, 
GREATER_EQUAL, Math.nextAfter(12.345, Float.MAX_VALUE)),
                         KuduPredicate.newComparisonPredicate(doubleCol, 
GREATER, 12.345));
+    Assert.assertEquals(
+        KuduPredicate.newComparisonPredicate(decimal32Col, GREATER_EQUAL, 
BigDecimal.valueOf(12346, 2)),
+        KuduPredicate.newComparisonPredicate(decimal32Col, GREATER, 
BigDecimal.valueOf(12345, 2)));
     Assert.assertEquals(KuduPredicate.newComparisonPredicate(stringCol, 
GREATER_EQUAL, "a\0"),
                         KuduPredicate.newComparisonPredicate(stringCol, 
GREATER, "a"));
     Assert.assertEquals(KuduPredicate.newComparisonPredicate(binaryCol, 
GREATER_EQUAL, new byte[] { (byte) 10, (byte) 0 }),
@@ -945,6 +1027,15 @@ public class TestKuduPredicate {
                         KuduPredicate.none(floatCol));
     Assert.assertEquals(KuduPredicate.newComparisonPredicate(doubleCol, LESS, 
Double.NEGATIVE_INFINITY),
                         KuduPredicate.none(doubleCol));
+    Assert.assertEquals(KuduPredicate.newComparisonPredicate(decimal32Col, 
LESS,
+        DecimalUtil.minValue(DecimalUtil.MAX_DECIMAL32_PRECISION, 2)),
+        KuduPredicate.none(decimal32Col));
+    Assert.assertEquals(KuduPredicate.newComparisonPredicate(decimal64Col, 
LESS,
+        DecimalUtil.minValue(DecimalUtil.MAX_DECIMAL64_PRECISION, 2)),
+        KuduPredicate.none(decimal64Col));
+    Assert.assertEquals(KuduPredicate.newComparisonPredicate(decimal128Col, 
LESS,
+        DecimalUtil.minValue(DecimalUtil.MAX_DECIMAL128_PRECISION, 2)),
+        KuduPredicate.none(decimal128Col));
     Assert.assertEquals(KuduPredicate.newComparisonPredicate(stringCol, LESS, 
""),
                         KuduPredicate.none(stringCol));
     Assert.assertEquals(KuduPredicate.newComparisonPredicate(binaryCol, LESS, 
new byte[] {}),
@@ -965,6 +1056,15 @@ public class TestKuduPredicate {
                         KuduPredicate.newIsNotNullPredicate(floatCol));
     Assert.assertEquals(KuduPredicate.newComparisonPredicate(doubleCol, 
GREATER_EQUAL, Double.NEGATIVE_INFINITY),
                         KuduPredicate.newIsNotNullPredicate(doubleCol));
+    Assert.assertEquals(KuduPredicate.newComparisonPredicate(decimal32Col, 
GREATER_EQUAL,
+        DecimalUtil.minValue(DecimalUtil.MAX_DECIMAL32_PRECISION, 2)),
+        KuduPredicate.newIsNotNullPredicate(decimal32Col));
+    Assert.assertEquals(KuduPredicate.newComparisonPredicate(decimal64Col, 
GREATER_EQUAL,
+        DecimalUtil.minValue(DecimalUtil.MAX_DECIMAL64_PRECISION, 2)),
+        KuduPredicate.newIsNotNullPredicate(decimal64Col));
+    Assert.assertEquals(KuduPredicate.newComparisonPredicate(decimal128Col, 
GREATER_EQUAL,
+        DecimalUtil.minValue(DecimalUtil.MAX_DECIMAL128_PRECISION, 2)),
+        KuduPredicate.newIsNotNullPredicate(decimal128Col));
     Assert.assertEquals(KuduPredicate.newComparisonPredicate(stringCol, 
GREATER_EQUAL, ""),
                         KuduPredicate.newIsNotNullPredicate(stringCol));
     Assert.assertEquals(KuduPredicate.newComparisonPredicate(binaryCol, 
GREATER_EQUAL, new byte[] {}),
@@ -1000,6 +1100,15 @@ public class TestKuduPredicate {
                         KuduPredicate.newComparisonPredicate(floatCol, EQUAL, 
123.456f).toString());
     Assert.assertEquals("`double` = 123.456",
                         KuduPredicate.newComparisonPredicate(doubleCol, EQUAL, 
123.456).toString());
+    Assert.assertEquals("`decimal32` = 123.45",
+        KuduPredicate.newComparisonPredicate(decimal32Col, EQUAL,
+            BigDecimal.valueOf(12345, 2)).toString());
+    Assert.assertEquals("`decimal64` = 123456789.10",
+        KuduPredicate.newComparisonPredicate(decimal64Col, EQUAL,
+            BigDecimal.valueOf(12345678910L, 2)).toString());
+    Assert.assertEquals("`decimal128` = 1234567891011121314.15",
+        KuduPredicate.newComparisonPredicate(decimal128Col, EQUAL,
+            new BigDecimal("1234567891011121314.15")).toString());
     Assert.assertEquals("`string` = \"my string\"",
                         KuduPredicate.newComparisonPredicate(stringCol, EQUAL, 
"my string").toString());
     Assert.assertEquals("`binary` = 0xAB01CD", 
KuduPredicate.newComparisonPredicate(

http://git-wip-us.apache.org/repos/asf/kudu/blob/4f34b69d/java/kudu-client/src/test/java/org/apache/kudu/client/TestPartialRow.java
----------------------------------------------------------------------
diff --git 
a/java/kudu-client/src/test/java/org/apache/kudu/client/TestPartialRow.java 
b/java/kudu-client/src/test/java/org/apache/kudu/client/TestPartialRow.java
index b4dd756..44e3c45 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestPartialRow.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestPartialRow.java
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.math.BigDecimal;
 import java.nio.ByteBuffer;
 
 import org.junit.Test;
@@ -51,6 +52,7 @@ public class TestPartialRow {
     assertEquals(ByteBuffer.wrap(new byte[] { 5, 6, 7, 8, 9 }), 
partialRow.getBinary("binary-bytebuffer"));
     assertTrue(partialRow.isSet("null"));
     assertTrue(partialRow.isNull("null"));
+    assertEquals(BigDecimal.valueOf(12345, 3), 
partialRow.getDecimal("decimal"));
   }
 
   @Test(expected = IllegalArgumentException.class)
@@ -199,6 +201,32 @@ public class TestPartialRow {
     partialRow.isSet(999);
   }
 
+  @Test(expected = IllegalArgumentException.class)
+  public void testAddInvalidPrecisionDecimal() {
+    PartialRow partialRow = getPartialRowWithAllTypes();
+    partialRow.addDecimal("decimal", BigDecimal.valueOf(123456, 3));
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testAddInvalidScaleDecimal() {
+    PartialRow partialRow = getPartialRowWithAllTypes();
+    partialRow.addDecimal("decimal", BigDecimal.valueOf(12345, 4));
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testAddInvalidCoercedScaleDecimal() {
+    PartialRow partialRow = getPartialRowWithAllTypes();
+    partialRow.addDecimal("decimal", BigDecimal.valueOf(12345, 2));
+  }
+
+  @Test
+  public void testAddCoercedScaleAndPrecisionDecimal() {
+    PartialRow partialRow = getPartialRowWithAllTypes();
+    partialRow.addDecimal("decimal", BigDecimal.valueOf(222, 1));
+    BigDecimal decimal = partialRow.getDecimal("decimal");
+    assertEquals("22.200", decimal.toString());
+  }
+
   @Test
   public void testToString() {
     Schema schema = BaseKuduTest.getSchemaWithAllTypes();
@@ -228,12 +256,96 @@ public class TestPartialRow {
     assertEquals("(int8 int8=42, int32 int32=42, double double=52.35, " +
                      "string string=\"fun with ütf\\0\", binary 
binary-bytebuffer=[2, 3, 4])",
                  row.toString());
+
+    row.addDecimal("decimal", BigDecimal.valueOf(12345, 3));
+    assertEquals("(int8 int8=42, int32 int32=42, double double=52.35, " +
+            "string string=\"fun with ütf\\0\", binary binary-bytebuffer=[2, 
3, 4], " +
+            "decimal(5, 3) decimal=12.345)",
+        row.toString());
+  }
+
+  @Test
+  public void testIncrementColumn() {
+    PartialRow partialRow = getPartialRowWithAllTypes();
+
+    // Boolean
+    int boolIndex = getColumnIndex(partialRow, "bool");
+    partialRow.addBoolean(boolIndex, false);
+    assertTrue(partialRow.incrementColumn(boolIndex));
+    assertEquals(true, partialRow.getBoolean(boolIndex));
+    assertFalse(partialRow.incrementColumn(boolIndex));
+
+    // Int8
+    int int8Index = getColumnIndex(partialRow, "int8");
+    partialRow.addByte(int8Index, (byte)(Byte.MAX_VALUE - 1));
+    assertTrue(partialRow.incrementColumn(int8Index));
+    assertEquals(Byte.MAX_VALUE, partialRow.getByte(int8Index));
+    assertFalse(partialRow.incrementColumn(int8Index));
+
+    // Int16
+    int int16Index = getColumnIndex(partialRow, "int16");
+    partialRow.addShort(int16Index, (short)(Short.MAX_VALUE - 1));
+    assertTrue(partialRow.incrementColumn(int16Index));
+    assertEquals(Short.MAX_VALUE, partialRow.getShort(int16Index));
+    assertFalse(partialRow.incrementColumn(int16Index));
+
+    // Int32
+    int int32Index = getColumnIndex(partialRow, "int32");
+    partialRow.addInt(int32Index, Integer.MAX_VALUE - 1);
+    assertTrue(partialRow.incrementColumn(int32Index));
+    assertEquals(Integer.MAX_VALUE, partialRow.getInt(int32Index));
+    assertFalse(partialRow.incrementColumn(int32Index));
+
+    // Int64
+    int int64Index = getColumnIndex(partialRow, "int64");
+    partialRow.addLong(int64Index, Long.MAX_VALUE - 1);
+    assertTrue(partialRow.incrementColumn(int64Index));
+    assertEquals(Long.MAX_VALUE, partialRow.getLong(int64Index));
+    assertFalse(partialRow.incrementColumn(int64Index));
+
+    // Float
+    int floatIndex = getColumnIndex(partialRow, "float");
+    partialRow.addFloat(floatIndex, Float.MAX_VALUE);
+    assertTrue(partialRow.incrementColumn(floatIndex));
+    assertEquals(Float.POSITIVE_INFINITY, partialRow.getFloat(floatIndex), 
0.0f);
+    assertFalse(partialRow.incrementColumn(floatIndex));
+
+    // Float
+    int doubleIndex = getColumnIndex(partialRow, "double");
+    partialRow.addDouble(doubleIndex, Double.MAX_VALUE);
+    assertTrue(partialRow.incrementColumn(doubleIndex));
+    assertEquals(Double.POSITIVE_INFINITY, partialRow.getDouble(doubleIndex), 
0.0);
+    assertFalse(partialRow.incrementColumn(doubleIndex));
+
+    // Decimal
+    int decimalIndex = getColumnIndex(partialRow, "decimal");
+    // Decimal with precision 5, scale 3 has a max of 99.999
+    partialRow.addDecimal(decimalIndex, new BigDecimal("99.998"));
+    assertTrue(partialRow.incrementColumn(decimalIndex));
+    assertEquals(new BigDecimal("99.999"), 
partialRow.getDecimal(decimalIndex));
+    assertFalse(partialRow.incrementColumn(decimalIndex));
+
+    // String
+    int stringIndex = getColumnIndex(partialRow, "string");
+    partialRow.addString(stringIndex, "hello");
+    assertTrue(partialRow.incrementColumn(stringIndex));
+    assertEquals("hello\0", partialRow.getString(stringIndex));
+
+    // Binary
+    int binaryIndex = getColumnIndex(partialRow, "binary-array");
+    partialRow.addBinary(binaryIndex, new byte[] { 0, 1, 2, 3, 4 });
+    assertTrue(partialRow.incrementColumn(binaryIndex));
+    assertArrayEquals(new byte[] { 0, 1, 2, 3, 4, 0 }, 
partialRow.getBinaryCopy(binaryIndex));
+  }
+
+  private int getColumnIndex(PartialRow partialRow, String columnName) {
+    return partialRow.getSchema().getColumnIndex(columnName);
   }
 
   private PartialRow getPartialRowWithAllTypes() {
     Schema schema = BaseKuduTest.getSchemaWithAllTypes();
     // Ensure we aren't missing any types
-    assertEquals(12, schema.getColumnCount());
+    assertEquals(13, schema.getColumnCount());
 
     PartialRow row = schema.newPartialRow();
     row.addByte("int8", (byte) 42);
@@ -249,6 +361,7 @@ public class TestPartialRow {
     ByteBuffer binaryBuffer = ByteBuffer.wrap(new byte[] { 5, 6, 7, 8, 9 });
     row.addBinary("binary-bytebuffer", binaryBuffer);
     row.setNull("null");
+    row.addDecimal("decimal", BigDecimal.valueOf(12345, 3));
     return row;
   }
 
@@ -270,6 +383,7 @@ public class TestPartialRow {
       case FLOAT: return partialRow.getFloat(columnName);
       case DOUBLE: return partialRow.getDouble(columnName);
       case BOOL: return partialRow.getBoolean(columnName);
+      case DECIMAL: return partialRow.getDecimal(columnName);
       default:
         throw new UnsupportedOperationException();
     }
@@ -287,6 +401,7 @@ public class TestPartialRow {
       case FLOAT: return partialRow.getFloat(columnIndex);
       case DOUBLE: return partialRow.getDouble(columnIndex);
       case BOOL: return partialRow.getBoolean(columnIndex);
+      case DECIMAL: return partialRow.getDecimal(columnIndex);
       default:
         throw new UnsupportedOperationException();
     }
@@ -304,6 +419,7 @@ public class TestPartialRow {
       case FLOAT: partialRow.addFloat(columnName, 52.35F); break;
       case DOUBLE: partialRow.addDouble(columnName, 53.35); break;
       case BOOL: partialRow.addBoolean(columnName, true); break;
+      case DECIMAL: partialRow.addDecimal(columnName, 
BigDecimal.valueOf(12345, 3)); break;
       default:
         throw new UnsupportedOperationException();
     }
@@ -321,6 +437,7 @@ public class TestPartialRow {
       case FLOAT: partialRow.addFloat(columnIndex, 52.35F); break;
       case DOUBLE: partialRow.addDouble(columnIndex, 53.35); break;
       case BOOL: partialRow.addBoolean(columnIndex, true); break;
+      case DECIMAL: partialRow.addDecimal(columnIndex, 
BigDecimal.valueOf(12345, 3)); break;
       default:
         throw new UnsupportedOperationException();
     }

http://git-wip-us.apache.org/repos/asf/kudu/blob/4f34b69d/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowResult.java
----------------------------------------------------------------------
diff --git 
a/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowResult.java 
b/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowResult.java
index 223ddc4..5196eda 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowResult.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowResult.java
@@ -20,6 +20,7 @@ import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import java.math.BigDecimal;
 import java.nio.ByteBuffer;
 
 import org.junit.BeforeClass;
@@ -61,6 +62,7 @@ public class TestRowResult extends BaseKuduTest {
     row.addBinary(9, bb);
     row.setNull(10);
     row.addLong(11, 11l);
+    row.addDecimal(12, BigDecimal.valueOf(12345, 3));
 
     KuduSession session = syncClient.newSession();
     session.apply(insert);
@@ -113,6 +115,9 @@ public class TestRowResult extends BaseKuduTest {
       assertEquals(11, rr.getLong(11));
       assertEquals(11, 
rr.getLong(allTypesSchema.getColumnByIndex(11).getName()));
 
+      assertEquals(BigDecimal.valueOf(12345, 3), rr.getDecimal(12));
+      assertEquals(BigDecimal.valueOf(12345, 3), 
rr.getDecimal(allTypesSchema.getColumnByIndex(12).getName()));
+
       // We test with the column name once since it's the same method for all 
types, unlike above.
       assertEquals(Type.INT8, 
rr.getColumnType(allTypesSchema.getColumnByIndex(0).getName()));
       assertEquals(Type.INT8, rr.getColumnType(0));
@@ -125,6 +130,7 @@ public class TestRowResult extends BaseKuduTest {
       assertEquals(Type.STRING, rr.getColumnType(7));
       assertEquals(Type.BINARY, rr.getColumnType(8));
       assertEquals(Type.UNIXTIME_MICROS, rr.getColumnType(11));
+      assertEquals(Type.DECIMAL, rr.getColumnType(12));
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/kudu/blob/4f34b69d/java/kudu-client/src/test/java/org/apache/kudu/client/TestScanPredicate.java
----------------------------------------------------------------------
diff --git 
a/java/kudu-client/src/test/java/org/apache/kudu/client/TestScanPredicate.java 
b/java/kudu-client/src/test/java/org/apache/kudu/client/TestScanPredicate.java
index d89800c..7682d6d 100644
--- 
a/java/kudu-client/src/test/java/org/apache/kudu/client/TestScanPredicate.java
+++ 
b/java/kudu-client/src/test/java/org/apache/kudu/client/TestScanPredicate.java
@@ -17,6 +17,7 @@
 
 package org.apache.kudu.client;
 
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.NavigableSet;
@@ -31,6 +32,7 @@ import org.apache.kudu.ColumnSchema;
 import org.apache.kudu.Schema;
 import org.apache.kudu.Type;
 import org.apache.kudu.client.KuduPredicate.ComparisonOp;
+import org.apache.kudu.util.DecimalUtil;
 
 public class TestScanPredicate extends BaseKuduTest {
 
@@ -170,6 +172,36 @@ public class TestScanPredicate extends BaseKuduTest {
     );
   }
 
+  // Returns a vector of decimal(4, 2) numbers from -50.50 (inclusive) to 50.50
+  // (exclusive) (100 values) and boundary values.
+  private NavigableSet<BigDecimal> createDecimalValues() {
+    NavigableSet<BigDecimal> values = new TreeSet<>();
+    for (long i = -50; i < 50; i++) {
+      values.add(BigDecimal.valueOf(i * 100 + i, 2));
+    }
+
+    values.add(BigDecimal.valueOf(-9999, 2));
+    values.add(BigDecimal.valueOf(-9998, 2));
+    values.add(BigDecimal.valueOf(9998, 2));
+    values.add(BigDecimal.valueOf(9999, 2));
+
+    return values;
+  }
+
+  private List<BigDecimal> createDecimalTestValues() {
+    return ImmutableList.of(
+        BigDecimal.valueOf(-9999, 2),
+        BigDecimal.valueOf(-9998, 2),
+        BigDecimal.valueOf(5100, 2),
+        BigDecimal.valueOf(-5000, 2),
+        BigDecimal.valueOf(0, 2),
+        BigDecimal.valueOf(4900, 2),
+        BigDecimal.valueOf(5000, 2),
+        BigDecimal.valueOf(9998, 2),
+        BigDecimal.valueOf(9999, 2)
+    );
+  }
+
   private NavigableSet<String> createStringValues() {
     return ImmutableSortedSet.of("", "\0", "\0\0", "a", "a\0", "a\0a", "aa\0");
   }
@@ -520,6 +552,69 @@ public class TestScanPredicate extends BaseKuduTest {
   }
 
   @Test
+  public void testDecimalPredicates() throws Exception {
+    ColumnSchema key = new ColumnSchema.ColumnSchemaBuilder("key", 
Type.INT64).key(true).build();
+    ColumnSchema val = new ColumnSchema.ColumnSchemaBuilder("value", 
Type.DECIMAL)
+        .typeAttributes(DecimalUtil.typeAttributes(4, 
2)).nullable(true).build();
+    Schema schema = new Schema(ImmutableList.of(key, val));
+
+    syncClient.createTable("decimal-table", schema, createTableOptions());
+    KuduTable table = syncClient.openTable("decimal-table");
+
+    NavigableSet<BigDecimal> values = createDecimalValues();
+    List<BigDecimal> testValues = createDecimalTestValues();
+    KuduSession session = syncClient.newSession();
+    session.setFlushMode(SessionConfiguration.FlushMode.MANUAL_FLUSH);
+    long i = 0;
+    for (BigDecimal value : values) {
+      Insert insert = table.newInsert();
+      insert.getRow().addLong("key", i++);
+      insert.getRow().addDecimal("value", value);
+      session.apply(insert);
+    }
+    Insert nullInsert = table.newInsert();
+    nullInsert.getRow().addLong("key", i++);
+    nullInsert.getRow().setNull("value");
+    session.apply(nullInsert);
+    session.flush();
+
+    ColumnSchema col = table.getSchema().getColumn("value");
+    Assert.assertEquals(values.size() + 1, countRows(table));
+
+    for (BigDecimal v : testValues) {
+      // value = v
+      KuduPredicate equal = KuduPredicate.newComparisonPredicate(col, 
ComparisonOp.EQUAL, v);
+      Assert.assertEquals(values.subSet(v, true, v, true).size(), 
countRows(table, equal));
+
+      // value >= v
+      KuduPredicate greaterEqual =
+          KuduPredicate.newComparisonPredicate(col, 
ComparisonOp.GREATER_EQUAL, v);
+      Assert.assertEquals(values.tailSet(v).size(), countRows(table, 
greaterEqual));
+
+      // value <= v
+      KuduPredicate lessEqual =
+          KuduPredicate.newComparisonPredicate(col, ComparisonOp.LESS_EQUAL, 
v);
+      Assert.assertEquals(values.headSet(v, true).size(), countRows(table, 
lessEqual));
+
+      // value > v
+      KuduPredicate greater =
+          KuduPredicate.newComparisonPredicate(col, ComparisonOp.GREATER, v);
+      Assert.assertEquals(values.tailSet(v, false).size(), countRows(table, 
greater));
+
+      // value < v
+      KuduPredicate less =
+          KuduPredicate.newComparisonPredicate(col, ComparisonOp.LESS, v);
+      Assert.assertEquals(values.headSet(v).size(), countRows(table, less));
+    }
+
+    KuduPredicate isNotNull = KuduPredicate.newIsNotNullPredicate(col);
+    Assert.assertEquals(values.size(), countRows(table, isNotNull));
+
+    KuduPredicate isNull = KuduPredicate.newIsNullPredicate(col);
+    Assert.assertEquals(1, countRows(table, isNull));
+  }
+
+  @Test
   public void testStringPredicates() throws Exception {
     Schema schema = createTableSchema(Type.STRING);
     syncClient.createTable("string-table", schema, createTableOptions());

Reply via email to