You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ma...@apache.org on 2015/08/23 19:15:26 UTC

[01/40] phoenix git commit: PHOENIX-2129 Fix ArrayToStringFunctionTest#testDate (Dumindu Buddhika)

Repository: phoenix
Updated Branches:
  refs/heads/calcite 35bd148e1 -> ab97f1ccd


PHOENIX-2129 Fix ArrayToStringFunctionTest#testDate (Dumindu Buddhika)


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/936de881
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/936de881
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/936de881

Branch: refs/heads/calcite
Commit: 936de881575423c9242d083e5852e82017905977
Parents: b38a624
Author: ramkrishna <ra...@gmail.com>
Authored: Mon Jul 20 22:52:39 2015 +0530
Committer: ramkrishna <ra...@gmail.com>
Committed: Mon Jul 20 22:52:39 2015 +0530

----------------------------------------------------------------------
 .../apache/phoenix/expression/ArrayToStringFunctionTest.java  | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/936de881/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java
index d97f117..5ca266d 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java
@@ -135,7 +135,6 @@ public class ArrayToStringFunctionTest {
     }
     
     @Test
-    @Ignore
     public void testDate() throws SQLException {
         PDataType type = PDateArray.INSTANCE;
         PDataType base = PDate.INSTANCE;
@@ -143,7 +142,11 @@ public class ArrayToStringFunctionTest {
         PhoenixArray arr = new PhoenixArray(base, o1);
         String delimiter = ", ";
         String nullString = "*";
-        String expected = "1970-01-01, 1970-01-01, 1970-01-01";
+        String expected = "";
+        for (int i = 0; i < o1.length - 1; i++) {
+            expected += o1[i].toString() + ", ";
+        }
+        expected += o1[o1.length - 1];
         test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
         test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
     }


[30/40] phoenix git commit: PHOENIX-2137 Range query on DECIMAL DESC sometimes incorrect

Posted by ma...@apache.org.
PHOENIX-2137 Range query on DECIMAL DESC sometimes incorrect


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/5330c079
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/5330c079
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/5330c079

Branch: refs/heads/calcite
Commit: 5330c0794e143014f5bd67114e3fc87c53015789
Parents: d401fa3
Author: James Taylor <jt...@salesforce.com>
Authored: Mon Aug 3 16:40:47 2015 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Tue Aug 11 01:59:37 2015 -0700

----------------------------------------------------------------------
 .../org/apache/phoenix/end2end/SortOrderIT.java | 110 ++++++++++++++++++-
 .../org/apache/phoenix/compile/ScanRanges.java  |   7 +-
 .../DescVarLengthFastByteComparisons.java       |  12 ++
 .../apache/phoenix/filter/SkipScanFilter.java   |  13 ++-
 .../java/org/apache/phoenix/query/KeyRange.java |  42 +++----
 .../apache/phoenix/schema/types/PDataType.java  |   3 +-
 .../java/org/apache/phoenix/util/ScanUtil.java  |  64 +++++++++--
 .../org/apache/phoenix/util/SchemaUtil.java     |   2 +-
 .../phoenix/compile/WhereOptimizerTest.java     |  20 ++++
 .../DescVarLengthFastByteComparisonsTest.java   |  45 ++++++++
 .../expression/SortOrderExpressionTest.java     |  13 ++-
 11 files changed, 288 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/5330c079/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java
index 0e8fb4f..9228ab5 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java
@@ -18,6 +18,7 @@
 package org.apache.phoenix.end2end;
 
 import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -28,12 +29,18 @@ import java.sql.Date;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Collections;
 import java.util.GregorianCalendar;
 import java.util.List;
 import java.util.Properties;
 
 import org.apache.commons.lang.ArrayUtils;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PDecimal;
 import org.apache.phoenix.util.PropertiesUtil;
 import org.junit.Assert;
 import org.junit.Test;
@@ -357,6 +364,102 @@ public class SortOrderIT extends BaseHBaseManagedTimeIT {
                 null, null, new OrderBy("id", OrderBy.Direction.DESC));
     }
     
+    @Test
+    public void descVarLengthAscPKGT() throws Exception {
+        String ddl = "CREATE TABLE " + TABLE + " (k1 INTEGER NOT NULL, k2 VARCHAR, CONSTRAINT pk PRIMARY KEY (k1, k2))";
+        Object[][] insertedRows = new Object[][]{{0, null}, {1, "a"}, {2, "b"}, {3, "ba"}, {4, "baa"}, {5, "c"}, {6, "d"}};
+        Object[][] expectedRows = new Object[][]{{3}, {4}, {5}, {6}};
+        runQueryTest(ddl, upsert("k1", "k2"), select("k1"), insertedRows, expectedRows,
+                new WhereCondition("k2", ">", "'b'"), null, null);
+    }
+        
+    @Test
+    public void descVarLengthDescPKGT() throws Exception {
+        String ddl = "CREATE TABLE " + TABLE + " (k1 INTEGER NOT NULL, k2 VARCHAR, CONSTRAINT pk PRIMARY KEY (k1, k2 desc))";
+        Object[][] insertedRows = new Object[][]{{0, null}, {1, "a"}, {2, "b"}, {3, "ba"}, {4, "baa"}, {5, "c"}, {6, "d"}};
+        Object[][] expectedRows = new Object[][]{{3}, {4}, {5}, {6}};
+        runQueryTest(ddl, upsert("k1", "k2"), select("k1"), insertedRows, expectedRows,
+                new WhereCondition("k2", ">", "'b'"), null, null);
+    }
+        
+    @Test
+    public void descVarLengthDescPKLTE() throws Exception {
+        String ddl = "CREATE TABLE " + TABLE + " (k1 INTEGER NOT NULL, k2 VARCHAR, CONSTRAINT pk PRIMARY KEY (k1, k2 desc))";
+        Object[][] insertedRows = new Object[][]{{0, null}, {1, "a"}, {2, "b"}, {3, "ba"}, {4, "bb"}, {5, "bc"}, {6, "bba"}, {7, "c"}};
+        Object[][] expectedRows = new Object[][]{{1}, {2}, {3}, {4}};
+        runQueryTest(ddl, upsert("k1", "k2"), select("k1"), insertedRows, expectedRows,
+                new WhereCondition("k2", "<=", "'bb'"), null, null);
+    }
+        
+    @Test
+    public void descVarLengthAscPKLTE() throws Exception {
+        String ddl = "CREATE TABLE " + TABLE + " (k1 INTEGER NOT NULL, k2 VARCHAR, CONSTRAINT pk PRIMARY KEY (k1, k2))";
+        Object[][] insertedRows = new Object[][]{{0, null}, {1, "a"}, {2, "b"}, {3, "ba"}, {4, "bb"}, {5, "bc"}, {6, "bba"}, {7, "c"}};
+        Object[][] expectedRows = new Object[][]{{1}, {2}, {3}, {4}};
+        runQueryTest(ddl, upsert("k1", "k2"), select("k1"), insertedRows, expectedRows,
+                new WhereCondition("k2", "<=", "'bb'"), null, null);
+    }
+        
+   @Test
+    public void testNonPKCompare() throws Exception {
+        List<Integer> expectedResults = Lists.newArrayList(2,3,4);
+        Integer[] saltBuckets = new Integer[] {null,3};
+        PDataType[] dataTypes = new PDataType[] {PDecimal.INSTANCE};
+        for (Integer saltBucket : saltBuckets) {
+            for (PDataType dataType : dataTypes) {
+                for (SortOrder sortOrder : SortOrder.values()) {
+                    testCompareCompositeKey(saltBucket, dataType, sortOrder, "", expectedResults, "");
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testSkipScanCompare() throws Exception {
+        List<Integer> expectedResults = Lists.newArrayList(2,4);
+        List<Integer> rExpectedResults = new ArrayList<>(expectedResults);
+        Collections.reverse(rExpectedResults);
+        Integer[] saltBuckets = new Integer[] {null,3};
+        PDataType[] dataTypes = new PDataType[] {PDecimal.INSTANCE};
+        for (Integer saltBucket : saltBuckets) {
+            for (PDataType dataType : dataTypes) {
+                for (SortOrder sortOrder : SortOrder.values()) {
+                    testCompareCompositeKey(saltBucket, dataType, sortOrder, "k1 in (2,4)", expectedResults, "");
+                    testCompareCompositeKey(saltBucket, dataType, sortOrder, "k1 in (2,4)", rExpectedResults, "ORDER BY k1 DESC");
+                }
+            }
+        }
+    }
+
+    private void testCompareCompositeKey(Integer saltBuckets, PDataType dataType, SortOrder sortOrder, String whereClause, List<Integer> expectedResults, String orderBy) throws SQLException {
+        String tableName = "t_" + saltBuckets + "_" + dataType + "_" + sortOrder;
+        String ddl = "create table if not exists " + tableName + " (k1 bigint not null, k2 " + dataType.getSqlTypeName() + (dataType.isFixedWidth() ? " not null" : "") + ", constraint pk primary key (k1,k2 " + sortOrder + "))" + (saltBuckets == null ? "" : (" SALT_BUCKETS= " + saltBuckets));
+        Connection conn = DriverManager.getConnection(getUrl(), PropertiesUtil.deepCopy(TEST_PROPERTIES));
+        conn.createStatement().execute(ddl);
+        if (!dataType.isFixedWidth()) {
+            conn.createStatement().execute("upsert into " + tableName + " values (0, null)");
+        }
+        conn.createStatement().execute("upsert into "  + tableName + " values (1, 0.99)");
+        conn.createStatement().execute("upsert into " + tableName + " values (2, 1.01)");
+        conn.createStatement().execute("upsert into "  + tableName + " values (3, 2.0)");
+        conn.createStatement().execute("upsert into " + tableName + " values (4, 1.001)");
+        conn.commit();
+
+        String query = "select k1 from " + tableName + " where " + (whereClause.length() > 0 ? (whereClause + " AND ") : "") + " k2>1.0 " + (orderBy.length() == 0 ? "" : orderBy);
+        try {
+            ResultSet rs = conn.createStatement().executeQuery(query);
+
+            for (int k : expectedResults) {
+                assertTrue (tableName, rs.next());
+                assertEquals(tableName, k,rs.getInt(1));
+            }
+
+            assertFalse(tableName, rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
     private void runQueryTest(String ddl, String columnName, Object[][] rows, Object[][] expectedRows) throws Exception {
         runQueryTest(ddl, new String[]{columnName}, rows, expectedRows, null);
     }
@@ -546,8 +649,13 @@ public class SortOrderIT extends BaseHBaseManagedTimeIT {
                 return ">";
             } else if (operator.equals(">")) {
                 return "<";
+            } else if (operator.equals(">=")) {
+                return "<=";
+            } else if (operator.equals("<=")) {
+                return ">=";
+            } else {
+                return operator;
             }
-            return operator;
         }
     }
     

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5330c079/phoenix-core/src/main/java/org/apache/phoenix/compile/ScanRanges.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ScanRanges.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ScanRanges.java
index 80cfbfe..298cd4e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/ScanRanges.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ScanRanges.java
@@ -37,6 +37,7 @@ import org.apache.phoenix.schema.RowKeySchema;
 import org.apache.phoenix.schema.SaltingUtil;
 import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.ScanUtil;
+import org.apache.phoenix.util.ScanUtil.BytesComparator;
 import org.apache.phoenix.util.SchemaUtil;
 
 import com.google.common.collect.ImmutableList;
@@ -75,10 +76,12 @@ public class ScanRanges {
                         stripPrefix(minMaxRange.getUpperRange(),offset), 
                         minMaxRange.upperUnbound());
             }
+            // We have full keys here, so use field from our varbinary schema
+            BytesComparator comparator = ScanUtil.getComparator(SchemaUtil.VAR_BINARY_SCHEMA.getField(0));
             for (byte[] key : keys) {
                 // Filter now based on unsalted minMaxRange and ignore the point key salt byte
-                if ( unsaltedMinMaxRange.compareLowerToUpperBound(key, offset, key.length-offset, true) <= 0 &&
-                     unsaltedMinMaxRange.compareUpperToLowerBound(key, offset, key.length-offset, true) >= 0) {
+                if ( unsaltedMinMaxRange.compareLowerToUpperBound(key, offset, key.length-offset, true, comparator) <= 0 &&
+                     unsaltedMinMaxRange.compareUpperToLowerBound(key, offset, key.length-offset, true, comparator) >= 0) {
                     keyRanges.add(KeyRange.getKeyRange(key));
                 }
             }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5330c079/phoenix-core/src/main/java/org/apache/phoenix/execute/DescVarLengthFastByteComparisons.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/DescVarLengthFastByteComparisons.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/DescVarLengthFastByteComparisons.java
index 40960e0..67d23fc 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/DescVarLengthFastByteComparisons.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/DescVarLengthFastByteComparisons.java
@@ -90,6 +90,12 @@ public class DescVarLengthFastByteComparisons {
             public int compareTo(byte[] buffer1, int offset1, int length1, byte[] buffer2, int offset2, int length2) {
                 // Short circuit equal case
                 if (buffer1 == buffer2 && offset1 == offset2 && length1 == length2) { return 0; }
+                if (length1 == 0 && length2 != 0) { // nulls sort first, even for descending
+                    return -1; 
+                } 
+                if (length2 == 0 && length1 != 0) { // nulls sort first, even for descending
+                    return 1; 
+                }
                 // Bring WritableComparator code local
                 int end1 = offset1 + length1;
                 int end2 = offset2 + length2;
@@ -166,6 +172,12 @@ public class DescVarLengthFastByteComparisons {
             public int compareTo(byte[] buffer1, int offset1, int length1, byte[] buffer2, int offset2, int length2) {
                 // Short circuit equal case
                 if (buffer1 == buffer2 && offset1 == offset2 && length1 == length2) { return 0; }
+                if (length1 == 0 && length2 != 0) { // nulls sort first, even for descending
+                    return -1; 
+                }
+                if (length2 == 0 && length1 != 0) { // nulls sort first, even for descending
+                    return 1; 
+                }
                 int minLength = Math.min(length1, length2);
                 int minWords = minLength / Longs.BYTES;
                 int offset1Adj = offset1 + BYTE_ARRAY_BASE_OFFSET;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5330c079/phoenix-core/src/main/java/org/apache/phoenix/filter/SkipScanFilter.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/filter/SkipScanFilter.java b/phoenix-core/src/main/java/org/apache/phoenix/filter/SkipScanFilter.java
index 4dc888d..ff58a18 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/filter/SkipScanFilter.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/filter/SkipScanFilter.java
@@ -40,6 +40,7 @@ import org.apache.phoenix.query.KeyRange.Bound;
 import org.apache.phoenix.schema.RowKeySchema;
 import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.ScanUtil;
+import org.apache.phoenix.util.ScanUtil.BytesComparator;
 import org.apache.phoenix.util.SchemaUtil;
 
 import com.google.common.base.Objects;
@@ -202,7 +203,7 @@ public class SkipScanFilter extends FilterBase implements Writable {
         if (!lowerUnbound) {
             // Find the position of the first slot of the lower range
             schema.next(ptr, 0, schema.iterator(lowerInclusiveKey,ptr), slotSpan[0]);
-            startPos = ScanUtil.searchClosestKeyRangeWithUpperHigherThanPtr(slots.get(0), ptr, 0);
+            startPos = ScanUtil.searchClosestKeyRangeWithUpperHigherThanPtr(slots.get(0), ptr, 0, schema.getField(0));
             // Lower range is past last upper range of first slot, so cannot possibly be in range
             if (startPos >= slots.get(0).size()) {
                 return false;
@@ -213,7 +214,7 @@ public class SkipScanFilter extends FilterBase implements Writable {
         if (!upperUnbound) {
             // Find the position of the first slot of the upper range
             schema.next(ptr, 0, schema.iterator(upperExclusiveKey,ptr), slotSpan[0]);
-            endPos = ScanUtil.searchClosestKeyRangeWithUpperHigherThanPtr(slots.get(0), ptr, startPos);
+            endPos = ScanUtil.searchClosestKeyRangeWithUpperHigherThanPtr(slots.get(0), ptr, startPos, schema.getField(0));
             // Upper range lower than first lower range of first slot, so cannot possibly be in range
 //            if (endPos == 0 && Bytes.compareTo(upperExclusiveKey, slots.get(0).get(0).getLowerRange()) <= 0) {
 //                return false;
@@ -222,7 +223,7 @@ public class SkipScanFilter extends FilterBase implements Writable {
             if (endPos >= slots.get(0).size()) {
                 upperUnbound = true;
                 endPos = slots.get(0).size()-1;
-            } else if (slots.get(0).get(endPos).compareLowerToUpperBound(upperExclusiveKey) >= 0) {
+            } else if (slots.get(0).get(endPos).compareLowerToUpperBound(upperExclusiveKey, ScanUtil.getComparator(schema.getField(0))) >= 0) {
                 // We know that the endPos range is higher than the previous range, but we need
                 // to test if it ends before the next range starts.
                 endPos--;
@@ -389,8 +390,10 @@ public class SkipScanFilter extends FilterBase implements Writable {
         int maxOffset = schema.iterator(currentKey, minOffset, length, ptr);
         schema.next(ptr, ScanUtil.getRowKeyPosition(slotSpan, i), maxOffset, slotSpan[i]);
         while (true) {
+            // Comparator depends on field in schema
+            BytesComparator comparator = ScanUtil.getComparator(schema.getField(ScanUtil.getRowKeyPosition(slotSpan, i)));
             // Increment to the next range while the upper bound of our current slot is less than our current key
-            while (position[i] < slots.get(i).size() && slots.get(i).get(position[i]).compareUpperToLowerBound(ptr) < 0) {
+            while (position[i] < slots.get(i).size() && slots.get(i).get(position[i]).compareUpperToLowerBound(ptr, comparator) < 0) {
                 position[i]++;
             }
             Arrays.fill(position, i+1, position.length, 0);
@@ -440,7 +443,7 @@ public class SkipScanFilter extends FilterBase implements Writable {
                     ByteUtil.nextKey(startKey, currentLength);
                 }
                 i = j;
-            } else if (slots.get(i).get(position[i]).compareLowerToUpperBound(ptr) > 0) {
+            } else if (slots.get(i).get(position[i]).compareLowerToUpperBound(ptr, comparator) > 0) {
                 // Our current key is less than the lower range of the current position in the current slot.
                 // Seek to the lower range, since it's bigger than the current key
                 setStartKey(ptr, minOffset, i);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5330c079/phoenix-core/src/main/java/org/apache/phoenix/query/KeyRange.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/KeyRange.java b/phoenix-core/src/main/java/org/apache/phoenix/query/KeyRange.java
index 0612046..366a123 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/KeyRange.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/KeyRange.java
@@ -32,6 +32,7 @@ import org.apache.hadoop.io.Writable;
 import org.apache.hadoop.io.WritableUtils;
 import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.util.ByteUtil;
+import org.apache.phoenix.util.ScanUtil.BytesComparator;
 
 import com.google.common.base.Function;
 import com.google.common.collect.ComparisonChain;
@@ -183,28 +184,28 @@ public class KeyRange implements Writable {
         return isSingleKey;
     }
     
-    public int compareLowerToUpperBound(ImmutableBytesWritable ptr, boolean isInclusive) {
-        return compareLowerToUpperBound(ptr.get(), ptr.getOffset(), ptr.getLength(), isInclusive);
+    public int compareLowerToUpperBound(ImmutableBytesWritable ptr, boolean isInclusive, BytesComparator comparator) {
+        return compareLowerToUpperBound(ptr.get(), ptr.getOffset(), ptr.getLength(), isInclusive, comparator);
     }
     
-    public int compareLowerToUpperBound(ImmutableBytesWritable ptr) {
-        return compareLowerToUpperBound(ptr, true);
+    public int compareLowerToUpperBound(ImmutableBytesWritable ptr, BytesComparator comparator) {
+        return compareLowerToUpperBound(ptr, true, comparator);
     }
     
-    public int compareUpperToLowerBound(ImmutableBytesWritable ptr, boolean isInclusive) {
-        return compareUpperToLowerBound(ptr.get(), ptr.getOffset(), ptr.getLength(), isInclusive);
+    public int compareUpperToLowerBound(ImmutableBytesWritable ptr, boolean isInclusive, BytesComparator comparator) {
+        return compareUpperToLowerBound(ptr.get(), ptr.getOffset(), ptr.getLength(), isInclusive, comparator);
     }
     
-    public int compareUpperToLowerBound(ImmutableBytesWritable ptr) {
-        return compareUpperToLowerBound(ptr, true);
+    public int compareUpperToLowerBound(ImmutableBytesWritable ptr, BytesComparator comparator) {
+        return compareUpperToLowerBound(ptr, true, comparator);
     }
     
-    public int compareLowerToUpperBound( byte[] b, int o, int l) {
-        return compareLowerToUpperBound(b,o,l,true);
+    public int compareLowerToUpperBound( byte[] b, int o, int l, BytesComparator comparator) {
+        return compareLowerToUpperBound(b,o,l,true, comparator);
     }
 
-    public int compareLowerToUpperBound( byte[] b) {
-        return compareLowerToUpperBound(b,0,b.length);
+    public int compareLowerToUpperBound( byte[] b, BytesComparator comparator) {
+        return compareLowerToUpperBound(b,0,b.length, comparator);
     }
 
     /**
@@ -213,15 +214,16 @@ public class KeyRange implements Writable {
      * @param o upper bound offset
      * @param l upper bound length
      * @param isInclusive upper bound inclusive
+     * @param comparator comparator used to do compare the byte array using offset and length
      * @return -1 if the lower bound is less than the upper bound,
      *          1 if the lower bound is greater than the upper bound,
      *          and 0 if they are equal.
      */
-    public int compareLowerToUpperBound( byte[] b, int o, int l, boolean isInclusive) {
+    public int compareLowerToUpperBound( byte[] b, int o, int l, boolean isInclusive, BytesComparator comparator) {
         if (lowerUnbound() || b == KeyRange.UNBOUND) {
             return -1;
         }
-        int cmp = Bytes.compareTo(lowerRange, 0, lowerRange.length, b, o, l);
+        int cmp = comparator.compare(lowerRange, 0, lowerRange.length, b, o, l);
         if (cmp > 0) {
             return 1;
         }
@@ -234,19 +236,19 @@ public class KeyRange implements Writable {
         return 1;
     }
     
-    public int compareUpperToLowerBound(byte[] b) {
-        return compareUpperToLowerBound(b,0,b.length);
+    public int compareUpperToLowerBound(byte[] b, BytesComparator comparator) {
+        return compareUpperToLowerBound(b,0,b.length, comparator);
     }
     
-    public int compareUpperToLowerBound(byte[] b, int o, int l) {
-        return compareUpperToLowerBound(b,o,l, true);
+    public int compareUpperToLowerBound(byte[] b, int o, int l, BytesComparator comparator) {
+        return compareUpperToLowerBound(b,o,l, true, comparator);
     }
     
-    public int compareUpperToLowerBound(byte[] b, int o, int l, boolean isInclusive) {
+    public int compareUpperToLowerBound(byte[] b, int o, int l, boolean isInclusive, BytesComparator comparator) {
         if (upperUnbound() || b == KeyRange.UNBOUND) {
             return 1;
         }
-        int cmp = Bytes.compareTo(upperRange, 0, upperRange.length, b, o, l);
+        int cmp = comparator.compare(upperRange, 0, upperRange.length, b, o, l);
         if (cmp > 0) {
             return 1;
         }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5330c079/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
index 43bab0e..d79de60 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
@@ -36,6 +36,7 @@ import org.apache.phoenix.schema.ConstraintViolationException;
 import org.apache.phoenix.schema.IllegalDataException;
 import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.util.ByteUtil;
+import org.apache.phoenix.util.ScanUtil;
 
 import com.google.common.base.Preconditions;
 import com.google.common.math.LongMath;
@@ -762,7 +763,7 @@ public abstract class PDataType<T> implements DataType<T>, Comparable<PDataType<
             }
             return (length1 - length2);
         }
-        return Bytes.compareTo(ba1, offset1, length1, ba2, offset2, length2) * (so1 == SortOrder.DESC ? -1 : 1);
+        return (so1 == SortOrder.DESC ? -1 : 1) * ScanUtil.getComparator(length1 == length2, so1).compare(ba1, offset1, length1, ba2, offset2, length2);
     }
 
     public final int compareTo(ImmutableBytesWritable ptr1, SortOrder ptr1SortOrder, ImmutableBytesWritable ptr2,

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5330c079/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
index 9d104ca..ae073e2 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
@@ -40,11 +40,13 @@ import org.apache.hadoop.hbase.filter.FilterList;
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.hadoop.hbase.io.TimeRange;
 import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.io.WritableComparator;
 import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
 import org.apache.phoenix.compile.ScanRanges;
 import org.apache.phoenix.compile.StatementContext;
 import org.apache.phoenix.coprocessor.BaseScannerRegionObserver;
 import org.apache.phoenix.coprocessor.MetaDataProtocol;
+import org.apache.phoenix.execute.DescVarLengthFastByteComparisons;
 import org.apache.phoenix.filter.BooleanExpressionFilter;
 import org.apache.phoenix.filter.SkipScanFilter;
 import org.apache.phoenix.query.KeyRange;
@@ -55,6 +57,7 @@ import org.apache.phoenix.query.QueryServicesOptions;
 import org.apache.phoenix.schema.PName;
 import org.apache.phoenix.schema.PNameFactory;
 import org.apache.phoenix.schema.RowKeySchema;
+import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.ValueSchema.Field;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.types.PVarbinary;
@@ -283,7 +286,15 @@ public class ScanUtil {
         for (int i = 0; i < position.length; i++) {
             position[i] = bound == Bound.LOWER ? 0 : slots.get(i).size()-1;
             KeyRange range = slots.get(i).get(position[i]);
-            maxLength += range.getRange(bound).length + (schema.getField(i + slotSpan[i]).getDataType().isFixedWidth() ? 0 : 1);
+            Field field = schema.getField(i + slotSpan[i]);
+            int keyLength = range.getRange(bound).length;
+            if (!field.getDataType().isFixedWidth()) {
+                keyLength++;
+                if (range.isUnbound(bound) && !range.isInclusive(bound) && field.getSortOrder() == SortOrder.DESC) {
+                    keyLength++;
+                }
+            }
+            maxLength += keyLength;
         }
         byte[] key = new byte[maxLength];
         int length = setKey(schema, slots, slotSpan, position, bound, key, 0, 0, position.length);
@@ -371,8 +382,8 @@ public class ScanUtil {
             // key slots would cause the flag to become true.
             lastInclusiveUpperSingleKey = range.isSingleKey() && inclusiveUpper;
             anyInclusiveUpperRangeKey |= !range.isSingleKey() && inclusiveUpper;
-            // A match for IS NULL or IS NOT NULL should not have a DESC_SEPARATOR_BYTE as nulls sort first
-            byte sepByte = SchemaUtil.getSeparatorByte(schema.rowKeyOrderOptimizable(), bytes.length == 0 || range == KeyRange.IS_NULL_RANGE || range == KeyRange.IS_NOT_NULL_RANGE, field);
+            // A null or empty byte array is always represented as a zero byte
+            byte sepByte = SchemaUtil.getSeparatorByte(schema.rowKeyOrderOptimizable(), bytes.length == 0, field);
             
             if (!isFixedWidth && ( fieldIndex < schema.getMaxFields() || inclusiveUpper || exclusiveLower || sepByte == QueryConstants.DESC_SEPARATOR_BYTE)) {
                 key[offset++] = sepByte;
@@ -383,7 +394,7 @@ public class ScanUtil {
             // If we are setting the lower bound with an exclusive range key, we need to bump the
             // slot up for each key part. For an upper bound, we bump up an inclusive key, but
             // only after the last key part.
-            if (!range.isSingleKey() && exclusiveLower) {
+            if (exclusiveLower) {
                 if (!ByteUtil.nextKey(key, offset)) {
                     // Special case for not being able to increment.
                     // In this case we return a negative byteOffset to
@@ -392,6 +403,14 @@ public class ScanUtil {
                     // have an end key specified.
                     return -byteOffset;
                 }
+                // We're filtering on values being non null here, but we still need the 0xFF
+                // terminator, since DESC keys ignore the last byte as it's expected to be 
+                // the terminator. Without this, we'd ignore the separator byte that was
+                // just added and incremented.
+                if (!isFixedWidth && bytes.length == 0 
+                    && SchemaUtil.getSeparatorByte(schema.rowKeyOrderOptimizable(), false, field) == QueryConstants.DESC_SEPARATOR_BYTE) {
+                    key[offset++] = QueryConstants.DESC_SEPARATOR_BYTE;
+                }
             }
         }
         if (lastInclusiveUpperSingleKey || anyInclusiveUpperRangeKey) {
@@ -409,7 +428,8 @@ public class ScanUtil {
         // byte.
         if (bound == Bound.LOWER) {
             while (--i >= schemaStartIndex && offset > byteOffset && 
-                    !schema.getField(--fieldIndex).getDataType().isFixedWidth() && 
+                    !(field=schema.getField(--fieldIndex)).getDataType().isFixedWidth() && 
+                    field.getSortOrder() == SortOrder.ASC &&
                     key[offset-1] == QueryConstants.SEPARATOR_BYTE) {
                 offset--;
                 fieldIndex -= slotSpan[i];
@@ -417,19 +437,47 @@ public class ScanUtil {
         }
         return offset - byteOffset;
     }
+    
+    public static interface BytesComparator {
+        public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2);
+    };
 
+    private static final BytesComparator DESC_VAR_WIDTH_COMPARATOR = new BytesComparator() {
+
+        @Override
+        public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
+            return DescVarLengthFastByteComparisons.compareTo(b1, s1, l1, b2, s2, l2);
+        }
+        
+    };
+    
+    private static final BytesComparator ASC_FIXED_WIDTH_COMPARATOR = new BytesComparator() {
+
+        @Override
+        public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
+            return WritableComparator.compareBytes(b1, s1, l1, b2, s2, l2);
+        }
+        
+    };
+    public static BytesComparator getComparator(boolean isFixedWidth, SortOrder sortOrder) {
+        return isFixedWidth || sortOrder == SortOrder.ASC ? ASC_FIXED_WIDTH_COMPARATOR : DESC_VAR_WIDTH_COMPARATOR;
+    }
+    public static BytesComparator getComparator(Field field) {
+        return getComparator(field.getDataType().isFixedWidth(),field.getSortOrder());
+    }
     /**
      * Perform a binary lookup on the list of KeyRange for the tightest slot such that the slotBound
      * of the current slot is higher or equal than the slotBound of our range. 
      * @return  the index of the slot whose slot bound equals or are the tightest one that is 
      *          smaller than rangeBound of range, or slots.length if no bound can be found.
      */
-    public static int searchClosestKeyRangeWithUpperHigherThanPtr(List<KeyRange> slots, ImmutableBytesWritable ptr, int lower) {
+    public static int searchClosestKeyRangeWithUpperHigherThanPtr(List<KeyRange> slots, ImmutableBytesWritable ptr, int lower, Field field) {
         int upper = slots.size() - 1;
         int mid;
+        BytesComparator comparator = ScanUtil.getComparator(field.getDataType().isFixedWidth(), field.getSortOrder());
         while (lower <= upper) {
             mid = (lower + upper) / 2;
-            int cmp = slots.get(mid).compareUpperToLowerBound(ptr, true);
+            int cmp = slots.get(mid).compareUpperToLowerBound(ptr, true, comparator);
             if (cmp < 0) {
                 lower = mid + 1;
             } else if (cmp > 0) {
@@ -439,7 +487,7 @@ public class ScanUtil {
             }
         }
         mid = (lower + upper) / 2;
-        if (mid == 0 && slots.get(mid).compareUpperToLowerBound(ptr, true) > 0) {
+        if (mid == 0 && slots.get(mid).compareUpperToLowerBound(ptr, true, comparator) > 0) {
             return mid;
         } else {
             return ++mid;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5330c079/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
index d01bf39..5414d4f 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
@@ -625,7 +625,7 @@ public class SchemaUtil {
     }
 
     public static int getMaxKeyLength(RowKeySchema schema, List<List<KeyRange>> slots) {
-        int maxKeyLength = getTerminatorCount(schema);
+        int maxKeyLength = getTerminatorCount(schema) * 2;
         for (List<KeyRange> slot : slots) {
             int maxSlotLength = 0;
             for (KeyRange range : slot) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5330c079/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java
index 227cbd7..79ec3f5 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java
@@ -32,6 +32,7 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.math.BigDecimal;
 import java.sql.Connection;
 import java.sql.Date;
 import java.sql.DriverManager;
@@ -56,9 +57,12 @@ import org.apache.phoenix.query.BaseConnectionlessQueryTest;
 import org.apache.phoenix.query.KeyRange;
 import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.schema.ColumnNotFoundException;
+import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.types.PChar;
 import org.apache.phoenix.schema.types.PDate;
+import org.apache.phoenix.schema.types.PDecimal;
 import org.apache.phoenix.schema.types.PInteger;
+import org.apache.phoenix.schema.types.PLong;
 import org.apache.phoenix.schema.types.PUnsignedLong;
 import org.apache.phoenix.schema.types.PVarchar;
 import org.apache.phoenix.util.ByteUtil;
@@ -135,6 +139,22 @@ public class WhereOptimizerTest extends BaseConnectionlessQueryTest {
     }
 
     @Test
+    public void testDescDecimalRange() throws SQLException {
+        String ddl = "create table t (k1 bigint not null, k2 decimal, constraint pk primary key (k1,k2 desc))";
+        Connection conn = DriverManager.getConnection(getUrl(), PropertiesUtil.deepCopy(TEST_PROPERTIES));
+        conn.createStatement().execute(ddl);
+        String query = "select * from t where k1 in (1,2) and k2>1.0";
+        Scan scan = compileStatement(query).getScan();
+
+        byte[] startRow = ByteUtil.concat(PLong.INSTANCE.toBytes(1), ByteUtil.nextKey(QueryConstants.SEPARATOR_BYTE_ARRAY), QueryConstants.DESC_SEPARATOR_BYTE_ARRAY);
+        byte[] upperValue = PDecimal.INSTANCE.toBytes(BigDecimal.valueOf(1.0));
+        byte[] stopRow = ByteUtil.concat(PLong.INSTANCE.toBytes(2), SortOrder.invert(upperValue,0,upperValue.length), QueryConstants.DESC_SEPARATOR_BYTE_ARRAY);
+        assertTrue(scan.getFilter() instanceof SkipScanFilter);
+        assertArrayEquals(startRow, scan.getStartRow());
+        assertArrayEquals(stopRow, scan.getStopRow());
+    }
+
+    @Test
     public void testSingleCharPaddedKeyExpression() throws SQLException {
         String tenantId = "1";
         String query = "select * from atable where organization_id='" + tenantId + "'";

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5330c079/phoenix-core/src/test/java/org/apache/phoenix/execute/DescVarLengthFastByteComparisonsTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/execute/DescVarLengthFastByteComparisonsTest.java b/phoenix-core/src/test/java/org/apache/phoenix/execute/DescVarLengthFastByteComparisonsTest.java
new file mode 100644
index 0000000..106471b
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/execute/DescVarLengthFastByteComparisonsTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.phoenix.execute;
+
+import static org.junit.Assert.assertTrue;
+
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.util.ByteUtil;
+import org.junit.Test;
+
+public class DescVarLengthFastByteComparisonsTest {
+    
+    @Test
+    public void testNullIsSmallest() {
+        byte[] b1 = ByteUtil.EMPTY_BYTE_ARRAY;
+        byte[] b2 = Bytes.toBytes("a");
+        int cmp = DescVarLengthFastByteComparisons.compareTo(b1, 0, b1.length, b2, 0, b2.length);
+        assertTrue(cmp < 0);
+        cmp = DescVarLengthFastByteComparisons.compareTo(b2, 0, b2.length, b1, 0, b1.length);
+        assertTrue(cmp > 0);
+    }
+    
+    @Test
+    public void testShorterSubstringIsBigger() {
+        byte[] b1 = Bytes.toBytes("ab");
+        byte[] b2 = Bytes.toBytes("a");
+        int cmp = DescVarLengthFastByteComparisons.compareTo(b1, 0, b1.length, b2, 0, b2.length);
+        assertTrue(cmp < 0);
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5330c079/phoenix-core/src/test/java/org/apache/phoenix/expression/SortOrderExpressionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/SortOrderExpressionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/SortOrderExpressionTest.java
index b9ee0eb..e2ab684 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/expression/SortOrderExpressionTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/SortOrderExpressionTest.java
@@ -292,17 +292,20 @@ public class SortOrderExpressionTest {
     }
     
     private void runCompareTest(CompareOp op, boolean expectedResult, Object lhsValue, PDataType lhsDataType, Object rhsValue, PDataType rhsDataType) throws Exception {
-        List<Expression> args = Lists.newArrayList(getLiteral(lhsValue, lhsDataType), getLiteral(rhsValue, rhsDataType));
-        evaluateAndAssertResult(new ComparisonExpression(args, op), expectedResult, "lhsDataType: " + lhsDataType + " rhsDataType: " + rhsDataType);
+        List<Expression> args;
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+
+        args = Lists.newArrayList(getLiteral(lhsValue, lhsDataType), getLiteral(rhsValue, rhsDataType));
+        evaluateAndAssertResult(ComparisonExpression.create(op, args, ptr, true), expectedResult, "lhsDataType: " + lhsDataType + " rhsDataType: " + rhsDataType);
         
         args = Lists.newArrayList(getInvertedLiteral(lhsValue, lhsDataType), getLiteral(rhsValue, rhsDataType));
-        evaluateAndAssertResult(new ComparisonExpression(args, op), expectedResult, "lhs (inverted) dataType: " + lhsDataType + " rhsDataType: " + rhsDataType);
+        evaluateAndAssertResult(ComparisonExpression.create(op, args, ptr, true), expectedResult, "lhs (inverted) dataType: " + lhsDataType + " rhsDataType: " + rhsDataType);
         
         args = Lists.newArrayList(getLiteral(lhsValue, lhsDataType), getInvertedLiteral(rhsValue, rhsDataType));
-        evaluateAndAssertResult(new ComparisonExpression(args, op), expectedResult, "lhsDataType: " + lhsDataType + " rhs (inverted) dataType: " + rhsDataType);
+        evaluateAndAssertResult(ComparisonExpression.create(op, args, ptr, true), expectedResult, "lhsDataType: " + lhsDataType + " rhs (inverted) dataType: " + rhsDataType);
         
         args = Lists.newArrayList(getInvertedLiteral(lhsValue, lhsDataType), getInvertedLiteral(rhsValue, rhsDataType));
-        evaluateAndAssertResult(new ComparisonExpression(args, op), expectedResult, "lhs (inverted) dataType: " + lhsDataType + " rhs (inverted) dataType: " + rhsDataType);                
+        evaluateAndAssertResult(ComparisonExpression.create(op, args, ptr, true), expectedResult, "lhs (inverted) dataType: " + lhsDataType + " rhs (inverted) dataType: " + rhsDataType);                
     }
     
     private void evaluateAndAssertResult(Expression expression, Object expectedResult) {


[35/40] phoenix git commit: PHOENIX-2177 Adding a column to the view shouldn't call admin.modifyTable() for the base table

Posted by ma...@apache.org.
PHOENIX-2177 Adding a column to the view shouldn't call admin.modifyTable() for the base table


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/8a1566c0
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/8a1566c0
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/8a1566c0

Branch: refs/heads/calcite
Commit: 8a1566c03ad24b2ffa5515b55918d9dc4f03efac
Parents: 5c04843
Author: Samarth <sa...@salesforce.com>
Authored: Thu Aug 13 12:24:50 2015 -0700
Committer: Samarth <sa...@salesforce.com>
Committed: Thu Aug 13 12:25:48 2015 -0700

----------------------------------------------------------------------
 .../phoenix/end2end/AlterTableWithViewsIT.java  | 40 ++++++++++++++++++++
 .../query/ConnectionQueryServicesImpl.java      | 28 +++++++++++---
 .../org/apache/phoenix/query/QueryServices.java |  1 +
 .../phoenix/query/QueryServicesOptions.java     |  4 +-
 4 files changed, 66 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/8a1566c0/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java
index 22abd38..77738be 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java
@@ -22,6 +22,7 @@ import static org.apache.phoenix.query.QueryConstants.BASE_TABLE_BASE_COLUMN_COU
 import static org.apache.phoenix.query.QueryConstants.DIVERGED_VIEW_BASE_COLUMN_COUNT;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -35,6 +36,8 @@ import java.sql.Statement;
 import java.util.List;
 import java.util.Properties;
 
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.phoenix.compile.QueryPlan;
 import org.apache.phoenix.exception.SQLExceptionCode;
 import org.apache.phoenix.jdbc.PhoenixConnection;
@@ -48,6 +51,7 @@ import org.apache.phoenix.schema.PTableType;
 import org.apache.phoenix.util.IndexUtil;
 import org.apache.phoenix.util.PhoenixRuntime;
 import org.apache.phoenix.util.SchemaUtil;
+import org.junit.Assert;
 import org.junit.Test;
 
 import com.google.common.base.Objects;
@@ -1056,6 +1060,42 @@ public class AlterTableWithViewsIT extends BaseHBaseManagedTimeIT {
         }
     }
     
+    @Test
+    public void testAlteringViewConditionallyModifiesHTableMetadata() throws Exception {
+        String baseTable = "testAlteringViewConditionallyModifiesBaseTable".toUpperCase();
+        String view1 = "view1".toUpperCase();
+        try (Connection conn = DriverManager.getConnection(getUrl())) {
+            String baseTableDDL = "CREATE TABLE " + baseTable + " (TENANT_ID VARCHAR NOT NULL, PK1 VARCHAR NOT NULL, V1 VARCHAR, V2 VARCHAR, V3 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, PK1)) MULTI_TENANT = true ";
+            conn.createStatement().execute(baseTableDDL);
+            HTableDescriptor tableDesc1 = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin().getTableDescriptor(Bytes.toBytes(baseTable)); 
+            try (Connection tenant1Conn = getTenantConnection("tenant1")) {
+                String view1DDL = "CREATE VIEW " + view1 + " ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 CHAR(256)) AS SELECT * FROM " + baseTable;
+                tenant1Conn.createStatement().execute(view1DDL);
+                // This should not modify the base table
+                String alterView = "ALTER VIEW " + view1 + " ADD NEWCOL1 VARCHAR";
+                tenant1Conn.createStatement().execute(alterView);
+                HTableDescriptor tableDesc2 = tenant1Conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin().getTableDescriptor(Bytes.toBytes(baseTable));
+                assertEquals(tableDesc1, tableDesc2);
+                
+                // Add a new column family that doesn't already exist in the base table
+                alterView = "ALTER VIEW " + view1 + " ADD CF.NEWCOL2 VARCHAR";
+                tenant1Conn.createStatement().execute(alterView);
+                
+                // Verify that the column family now shows up in the base table descriptor
+                tableDesc2 = tenant1Conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin().getTableDescriptor(Bytes.toBytes(baseTable));
+                assertFalse(tableDesc2.equals(tableDesc1));
+                assertNotNull(tableDesc2.getFamily(Bytes.toBytes("CF")));
+                
+                // Add a column with an existing column family. This shouldn't modify the base table.
+                alterView = "ALTER VIEW " + view1 + " ADD CF.NEWCOL3 VARCHAR";
+                tenant1Conn.createStatement().execute(alterView);
+                HTableDescriptor tableDesc3 = tenant1Conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin().getTableDescriptor(Bytes.toBytes(baseTable));
+                assertTrue(tableDesc3.equals(tableDesc2));
+                assertNotNull(tableDesc3.getFamily(Bytes.toBytes("CF")));
+            }
+        }
+    }
+    
     private static long getTableSequenceNumber(PhoenixConnection conn, String tableName) throws SQLException {
         PTable table = conn.getMetaDataCache().getTable(new PTableKey(conn.getTenantId(), SchemaUtil.normalizeIdentifier(tableName)));
         return table.getSequenceNumber();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8a1566c0/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
index dede98d..22a6720 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
@@ -27,7 +27,6 @@ import static org.apache.phoenix.util.UpgradeUtil.upgradeTo4_5_0;
 
 import java.io.IOException;
 import java.sql.SQLException;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -1504,14 +1503,22 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
     
     @Override
     public MetaDataMutationResult addColumn(final List<Mutation> tableMetaData, PTable table, Map<String, List<Pair<String,Object>>> stmtProperties, Set<String> colFamiliesForPColumnsToBeAdded) throws SQLException {
-        List<Pair<byte[], Map<String, Object>>> families = new ArrayList<>(stmtProperties.size());
         Map<String, Object> tableProps = new HashMap<String, Object>();
-        HTableDescriptor tableDescriptor = separateAndValidateProperties(table, stmtProperties, colFamiliesForPColumnsToBeAdded, families, tableProps);
+        HTableDescriptor tableDescriptor = separateAndValidateProperties(table, stmtProperties, colFamiliesForPColumnsToBeAdded, tableProps);
         SQLException sqlE = null;
         if (tableDescriptor != null) {
             try {
-                boolean pollingNotNeeded = (!tableProps.isEmpty() && families.isEmpty() && colFamiliesForPColumnsToBeAdded.isEmpty());
-                modifyTable(table.getPhysicalName().getBytes(), tableDescriptor, !pollingNotNeeded);
+                boolean modifyHTable = true;
+                if (table.getType() == PTableType.VIEW) {
+                    boolean canViewsAddNewCF = props.getBoolean(QueryServices.ALLOW_VIEWS_ADD_NEW_CF_BASE_TABLE,
+                            QueryServicesOptions.DEFAULT_ALLOW_VIEWS_ADD_NEW_CF_BASE_TABLE);
+                    // When adding a column to a view, base physical table should only be modified when new column families are being added.  
+                    modifyHTable = canViewsAddNewCF && !existingColumnFamiliesForBaseTable(table.getPhysicalName()).containsAll(colFamiliesForPColumnsToBeAdded);
+                }
+                boolean pollingNotNeeded = (!tableProps.isEmpty() && !existingColumnFamilies(table).containsAll(colFamiliesForPColumnsToBeAdded));
+                if (modifyHTable) {
+                    modifyTable(table.getPhysicalName().getBytes(), tableDescriptor, !pollingNotNeeded);
+                }
             } catch (IOException e) {
                 sqlE = ServerUtil.parseServerException(e);
             } catch (InterruptedException e) {
@@ -1590,7 +1597,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
         return result;
     }
     
-    private HTableDescriptor separateAndValidateProperties(PTable table, Map<String, List<Pair<String, Object>>> properties, Set<String> colFamiliesForPColumnsToBeAdded, List<Pair<byte[], Map<String, Object>>> families, Map<String, Object> tableProps) throws SQLException {
+    private HTableDescriptor separateAndValidateProperties(PTable table, Map<String, List<Pair<String, Object>>> properties, Set<String> colFamiliesForPColumnsToBeAdded, Map<String, Object> tableProps) throws SQLException {
         Map<String, Map<String, Object>> stmtFamiliesPropsMap = new HashMap<>(properties.size());
         Map<String,Object> commonFamilyProps = new HashMap<>();
         boolean addingColumns = colFamiliesForPColumnsToBeAdded != null && colFamiliesForPColumnsToBeAdded.size() > 0;
@@ -1763,6 +1770,15 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
         return !isHColumnProperty(propName) && !TableProperty.isPhoenixTableProperty(propName);
     } 
     
+    private HashSet<String> existingColumnFamiliesForBaseTable(PName baseTableName) throws TableNotFoundException {
+        synchronized (latestMetaDataLock) {
+            throwConnectionClosedIfNullMetaData();
+            PTable table = latestMetaData.getTable(new PTableKey(null, baseTableName.getString()));
+            latestMetaDataLock.notifyAll();
+            return existingColumnFamilies(table);
+        }
+    }
+    
     private HashSet<String> existingColumnFamilies(PTable table) {
         List<PColumnFamily> cfs = table.getColumnFamilies();
         HashSet<String> cfNames = new HashSet<>(cfs.size());

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8a1566c0/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java
index 62b080c..080586d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java
@@ -168,6 +168,7 @@ public interface QueryServices extends SQLCloseable {
     public static final String FORCE_ROW_KEY_ORDER_ATTRIB = "phoenix.query.force.rowkeyorder";
     public static final String ALLOW_USER_DEFINED_FUNCTIONS_ATTRIB = "phoenix.functions.allowUserDefinedFunctions";
     public static final String COLLECT_REQUEST_LEVEL_METRICS = "phoenix.query.request.metrics.enabled";
+    public static final String ALLOW_VIEWS_ADD_NEW_CF_BASE_TABLE = "phoenix.view.allowNewColumnFamily";
     
 
     /**

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8a1566c0/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java
index ea81cf5..4b8f092 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java
@@ -18,6 +18,7 @@
 package org.apache.phoenix.query;
 
 import static org.apache.phoenix.query.QueryServices.ALLOW_ONLINE_TABLE_SCHEMA_UPDATE;
+import static org.apache.phoenix.query.QueryServices.ALLOW_VIEWS_ADD_NEW_CF_BASE_TABLE;
 import static org.apache.phoenix.query.QueryServices.CALL_QUEUE_PRODUCER_ATTRIB_NAME;
 import static org.apache.phoenix.query.QueryServices.CALL_QUEUE_ROUND_ROBIN_ATTRIB;
 import static org.apache.phoenix.query.QueryServices.COLLECT_REQUEST_LEVEL_METRICS;
@@ -74,7 +75,6 @@ import org.apache.hadoop.hbase.client.Consistency;
 import org.apache.hadoop.hbase.ipc.RpcControllerFactory;
 import org.apache.hadoop.hbase.ipc.controller.ClientRpcControllerFactory;
 import org.apache.hadoop.hbase.regionserver.wal.WALCellCodec;
-import org.apache.phoenix.schema.SaltingUtil;
 import org.apache.phoenix.trace.util.Tracing;
 import org.apache.phoenix.util.DateUtil;
 import org.apache.phoenix.util.ReadOnlyProps;
@@ -198,6 +198,7 @@ public class QueryServicesOptions {
     public static final boolean DEFAULT_FORCE_ROW_KEY_ORDER = false;
     public static final boolean DEFAULT_ALLOW_USER_DEFINED_FUNCTIONS = false;
     public static final boolean DEFAULT_REQUEST_LEVEL_METRICS_ENABLED = false;
+    public static final boolean DEFAULT_ALLOW_VIEWS_ADD_NEW_CF_BASE_TABLE = true;
 
     private final Configuration config;
 
@@ -255,6 +256,7 @@ public class QueryServicesOptions {
             .setIfUnset(USE_BYTE_BASED_REGEX_ATTRIB, DEFAULT_USE_BYTE_BASED_REGEX)
             .setIfUnset(FORCE_ROW_KEY_ORDER_ATTRIB, DEFAULT_FORCE_ROW_KEY_ORDER)
             .setIfUnset(COLLECT_REQUEST_LEVEL_METRICS, DEFAULT_REQUEST_LEVEL_METRICS_ENABLED)
+            .setIfUnset(ALLOW_VIEWS_ADD_NEW_CF_BASE_TABLE, DEFAULT_ALLOW_VIEWS_ADD_NEW_CF_BASE_TABLE);
             ;
         // HBase sets this to 1, so we reset it to something more appropriate.
         // Hopefully HBase will change this, because we can't know if a user set


[19/40] phoenix git commit: PHOENIX-2141 ComparisonExpression should return Boolean null if either operand is null

Posted by ma...@apache.org.
PHOENIX-2141 ComparisonExpression should return Boolean null if either operand is null


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/c0d0c79e
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/c0d0c79e
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/c0d0c79e

Branch: refs/heads/calcite
Commit: c0d0c79e1ca487d69a036b36dda280e20a6ed7e5
Parents: 69f22b5
Author: maryannxue <we...@intel.com>
Authored: Mon Jul 27 14:50:16 2015 -0400
Committer: maryannxue <we...@intel.com>
Committed: Mon Jul 27 14:50:16 2015 -0400

----------------------------------------------------------------------
 .../phoenix/compile/ExpressionCompiler.java     |  3 +
 .../apache/phoenix/compile/HavingCompiler.java  |  2 +-
 .../apache/phoenix/compile/WhereCompiler.java   |  2 +-
 .../apache/phoenix/compile/WhereOptimizer.java  |  2 +-
 .../phoenix/expression/AndExpression.java       |  3 +
 .../expression/ComparisonExpression.java        |  4 +-
 .../phoenix/expression/LiteralExpression.java   | 23 ++++++--
 .../phoenix/expression/NullValueTest.java       | 59 ++++++++++++++++++++
 8 files changed, 89 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/c0d0c79e/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
index 1278494..1523dce 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
@@ -251,6 +251,9 @@ public class ExpressionCompiler extends UnsupportedAllParseNodeVisitor<Expressio
             if (child.getDataType() != PBoolean.INSTANCE) {
                 throw TypeMismatchException.newException(PBoolean.INSTANCE, child.getDataType(), child.toString());
             }
+            if (LiteralExpression.isBooleanNull(child)) {
+                return child;
+            }
             if (LiteralExpression.isFalse(child)) {
                 iterator.remove();
             }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c0d0c79e/phoenix-core/src/main/java/org/apache/phoenix/compile/HavingCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/HavingCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/HavingCompiler.java
index 224a9b4..9ccd2f0 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/HavingCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/HavingCompiler.java
@@ -54,7 +54,7 @@ public class HavingCompiler {
         if (expression.getDataType() != PBoolean.INSTANCE) {
             throw TypeMismatchException.newException(PBoolean.INSTANCE, expression.getDataType(), expression.toString());
         }
-        if (LiteralExpression.isFalse(expression)) {
+        if (LiteralExpression.isBooleanFalseOrNull(expression)) {
             context.setScanRanges(ScanRanges.NOTHING);
             return null;
         } else if (LiteralExpression.isTrue(expression)) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c0d0c79e/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java
index 9631850..13963d7 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java
@@ -235,7 +235,7 @@ public class WhereCompiler {
     private static void setScanFilter(StatementContext context, FilterableStatement statement, Expression whereClause, boolean disambiguateWithFamily, boolean hashJoinOptimization) {
         Scan scan = context.getScan();
 
-        if (LiteralExpression.isFalse(whereClause)) {
+        if (LiteralExpression.isBooleanFalseOrNull(whereClause)) {
             context.setScanRanges(ScanRanges.NOTHING);
         } else if (whereClause != null && !LiteralExpression.isTrue(whereClause) && !hashJoinOptimization) {
             Filter filter = null;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c0d0c79e/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
index 6dfae7e..601eee1 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
@@ -120,7 +120,7 @@ public class WhereOptimizer {
             context.setScanRanges(ScanRanges.EVERYTHING);
             return whereClause;
         }
-        if (LiteralExpression.isFalse(whereClause)) {
+        if (LiteralExpression.isBooleanFalseOrNull(whereClause)) {
             context.setScanRanges(ScanRanges.NOTHING);
             return null;
         }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c0d0c79e/phoenix-core/src/main/java/org/apache/phoenix/expression/AndExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/AndExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/AndExpression.java
index 70e94ca..29b024d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/AndExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/AndExpression.java
@@ -44,6 +44,9 @@ public class AndExpression extends AndOrExpression {
             if (child.getDataType() != PBoolean.INSTANCE) {
                 throw TypeMismatchException.newException(PBoolean.INSTANCE, child.getDataType(), child.toString());
             }
+            if (LiteralExpression.isBooleanNull(child)) {
+                return child;
+            }
             if (LiteralExpression.isFalse(child)) {
                 return child;
             }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c0d0c79e/phoenix-core/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java
index 1c8df20..074ac0a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java
@@ -142,7 +142,7 @@ public class ComparisonExpression extends BaseCompoundExpression {
         if (lhsExpr instanceof LiteralExpression) {
             lhsValue = ((LiteralExpression)lhsExpr).getValue();
             if (lhsValue == null) {
-                return LiteralExpression.newConstant(false, PBoolean.INSTANCE, lhsExpr.getDeterminism());
+                return LiteralExpression.newConstant(null, PBoolean.INSTANCE, lhsExpr.getDeterminism());
             }
         }
         Object rhsValue = null;
@@ -150,7 +150,7 @@ public class ComparisonExpression extends BaseCompoundExpression {
         if (rhsExpr instanceof LiteralExpression) {
             rhsValue = ((LiteralExpression)rhsExpr).getValue();
             if (rhsValue == null) {
-                return LiteralExpression.newConstant(false, PBoolean.INSTANCE, rhsExpr.getDeterminism());
+                return LiteralExpression.newConstant(null, PBoolean.INSTANCE, rhsExpr.getDeterminism());
             }
         }
         if (lhsValue != null && rhsValue != null) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c0d0c79e/phoenix-core/src/main/java/org/apache/phoenix/expression/LiteralExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/LiteralExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/LiteralExpression.java
index 05bd9b3..e911aae 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/LiteralExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/LiteralExpression.java
@@ -89,10 +89,10 @@ public class LiteralExpression extends BaseTerminalExpression {
     }
 
     public static boolean isFalse(Expression child) {
-    	if (child!=null) {
-    		return child == BOOLEAN_EXPRESSIONS[child.getDeterminism().ordinal()];
-    	}
-    	return false;
+        if (child!=null) {
+            return child == BOOLEAN_EXPRESSIONS[child.getDeterminism().ordinal()];
+        }
+        return false;
     }
     
     public static boolean isTrue(Expression child) {
@@ -101,6 +101,21 @@ public class LiteralExpression extends BaseTerminalExpression {
     	}
     	return false;
     }
+
+    public static boolean isBooleanNull(Expression child) {
+    	if (child!=null) {
+    		return child == TYPED_NULL_EXPRESSIONS[PBoolean.INSTANCE.ordinal()+PDataType.values().length*child.getDeterminism().ordinal()];
+    	}
+    	return false;
+    }
+
+    public static boolean isBooleanFalseOrNull(Expression child) {
+        if (child!=null) {
+            return child == BOOLEAN_EXPRESSIONS[child.getDeterminism().ordinal()]
+                    || child == TYPED_NULL_EXPRESSIONS[PBoolean.INSTANCE.ordinal()+PDataType.values().length*child.getDeterminism().ordinal()];
+        }
+        return false;
+    }
     
     public static LiteralExpression newConstant(Object value) {
         return newConstant(value, Determinism.ALWAYS);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c0d0c79e/phoenix-core/src/test/java/org/apache/phoenix/expression/NullValueTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/NullValueTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/NullValueTest.java
new file mode 100644
index 0000000..d5addf0
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/NullValueTest.java
@@ -0,0 +1,59 @@
+package org.apache.phoenix.expression;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.util.Properties;
+
+import org.apache.phoenix.query.BaseConnectionlessQueryTest;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.junit.Test;
+
+public class NullValueTest extends BaseConnectionlessQueryTest {
+    
+    @Test
+    public void testComparisonExpressionWithNullOperands() throws Exception {
+        String[] query = {"SELECT 'a' >= ''", 
+                          "SELECT '' < 'a'", 
+                          "SELECT '' = ''"};
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        try {
+            for (String q : query) {
+                ResultSet rs = conn.createStatement().executeQuery(q);
+                assertTrue(rs.next());
+                assertNull(rs.getObject(1));
+                assertEquals(false, rs.getBoolean(1));
+                assertFalse(rs.next());
+            }
+        } finally {
+            conn.close();
+        }       
+    }
+    
+    @Test
+    public void testAndOrExpressionWithNullOperands() throws Exception {
+        String[] query = {"SELECT 'a' >= '' or '' < 'a'", 
+                          "SELECT 'a' >= '' and '' < 'a'"};
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        try {
+            for (String q : query) {
+                ResultSet rs = conn.createStatement().executeQuery(q);
+                assertTrue(rs.next());
+                assertNull(rs.getObject(1));
+                assertEquals(false, rs.getBoolean(1));
+                assertFalse(rs.next());
+            }
+        } finally {
+            conn.close();
+        }       
+    }
+
+}


[13/40] phoenix git commit: PHOENIX-2139 LIKE '%' is not filtering out null columns

Posted by ma...@apache.org.
PHOENIX-2139 LIKE '%' is not filtering out null columns


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/5076052d
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/5076052d
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/5076052d

Branch: refs/heads/calcite
Commit: 5076052d5a84194554da96894c27a3829ce6e75b
Parents: a50ead2
Author: James Taylor <ja...@apache.org>
Authored: Wed Jul 22 16:22:58 2015 -0700
Committer: James Taylor <ja...@apache.org>
Committed: Wed Jul 22 16:22:58 2015 -0700

----------------------------------------------------------------------
 .../main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/5076052d/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
index 314af2e..d27a349 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
@@ -491,7 +491,7 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho
                 where.append(COLUMN_NAME + " like '" + StringUtil.escapeStringConstant(colPattern) + "'" );
             }
         }
-        if (colPattern == null) {
+        if (colPattern == null || colPattern.length() == 0) {
             appendConjunction(where);
             where.append(COLUMN_NAME + " is not null" );
         }


[02/40] phoenix git commit: PHOENIX-2120 Padding character is not inverted as required for DESC CHAR columns

Posted by ma...@apache.org.
PHOENIX-2120 Padding character is not inverted as required for DESC CHAR columns


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/dcf845c2
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/dcf845c2
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/dcf845c2

Branch: refs/heads/calcite
Commit: dcf845c25eb9bd619a999d16ce9e2f548ce7b491
Parents: 936de88
Author: James Taylor <ja...@apache.org>
Authored: Mon Jul 20 17:52:53 2015 -0700
Committer: James Taylor <ja...@apache.org>
Committed: Mon Jul 20 17:53:18 2015 -0700

----------------------------------------------------------------------
 .../apache/phoenix/end2end/LpadFunctionIT.java  |  48 +++-
 .../org/apache/phoenix/compile/KeyPart.java     |   8 +-
 .../apache/phoenix/compile/WhereOptimizer.java  | 132 +++++++---
 .../UngroupedAggregateRegionObserver.java       |  33 ++-
 .../phoenix/expression/LiteralExpression.java   |   3 +-
 .../expression/function/InvertFunction.java     |   8 +-
 .../expression/function/PrefixFunction.java     |  13 +-
 .../expression/function/RTrimFunction.java      |  15 +-
 .../function/RoundDateExpression.java           |  12 +-
 .../function/RoundDecimalExpression.java        |  22 +-
 .../query/ConnectionQueryServicesImpl.java      |   8 +-
 .../org/apache/phoenix/schema/PTableImpl.java   |  25 +-
 .../apache/phoenix/schema/types/PBinary.java    |  28 +-
 .../org/apache/phoenix/schema/types/PChar.java  |  11 +
 .../apache/phoenix/schema/types/PDataType.java  |   1 +
 .../org/apache/phoenix/util/PhoenixRuntime.java |  43 +++-
 .../org/apache/phoenix/util/StringUtil.java     |   7 -
 .../org/apache/phoenix/util/UpgradeUtil.java    | 256 +++++++++++++------
 18 files changed, 495 insertions(+), 178 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/it/java/org/apache/phoenix/end2end/LpadFunctionIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/LpadFunctionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/LpadFunctionIT.java
index 4aa66c2..4070103 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/LpadFunctionIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/LpadFunctionIT.java
@@ -16,6 +16,7 @@
  */
 package org.apache.phoenix.end2end;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -27,8 +28,10 @@ import java.sql.ResultSet;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.TestUtil;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import com.google.common.collect.Lists;
@@ -107,26 +110,59 @@ public class LpadFunctionIT extends BaseHBaseManagedTimeIT {
         testLpad(conn, inputList, length, fillStringList, "pk", expectedOutputList);
     }
 
-    @Ignore
     @Test
     public void testCharPadding() throws Exception {
         ResultSet rs;
         Connection conn = DriverManager.getConnection(getUrl());
+        
+        conn.createStatement().execute("CREATE TABLE t (k CHAR(3) PRIMARY KEY)");
+        conn.createStatement().execute("UPSERT INTO t VALUES('a')");
+        conn.createStatement().execute("UPSERT INTO t VALUES('ab')");
+        conn.commit();
+        rs = conn.createStatement().executeQuery("SELECT * FROM t ORDER BY k");
+        assertTrue(rs.next());
+        assertEquals("a", rs.getString(1));
+        assertTrue(rs.next());
+        assertEquals("ab", rs.getString(1));
+        assertFalse(rs.next());
 
         conn.createStatement().execute("CREATE TABLE tdesc (k CHAR(3) PRIMARY KEY DESC)");
         conn.createStatement().execute("UPSERT INTO tdesc VALUES('a')");
+        conn.createStatement().execute("UPSERT INTO tdesc VALUES('ab')");
         conn.commit();
-        rs = conn.createStatement().executeQuery("SELECT * FROM tdesc");
+        rs = conn.createStatement().executeQuery("SELECT * FROM tdesc ORDER BY k DESC");
+        assertTrue(rs.next());
+        assertEquals("ab", rs.getString(1));
         assertTrue(rs.next());
         assertEquals("a", rs.getString(1));
         assertFalse(rs.next());
+    }
+
+    @Test
+    public void testBinaryPadding() throws Exception {
+        ResultSet rs;
+        Connection conn = DriverManager.getConnection(getUrl());
         
-        conn.createStatement().execute("CREATE TABLE t (k CHAR(3) PRIMARY KEY)");
+        conn.createStatement().execute("CREATE TABLE t (k BINARY(3) PRIMARY KEY)");
         conn.createStatement().execute("UPSERT INTO t VALUES('a')");
+        conn.createStatement().execute("UPSERT INTO t VALUES('ab')");
         conn.commit();
-        rs = conn.createStatement().executeQuery("SELECT * FROM t");
+        rs = conn.createStatement().executeQuery("SELECT * FROM t ORDER BY k");
         assertTrue(rs.next());
-        assertEquals("a", rs.getString(1));
+        assertArrayEquals(ByteUtil.concat(Bytes.toBytes("a"), QueryConstants.SEPARATOR_BYTE_ARRAY, QueryConstants.SEPARATOR_BYTE_ARRAY), rs.getBytes(1));
+        assertTrue(rs.next());
+        assertArrayEquals(ByteUtil.concat(Bytes.toBytes("ab"), QueryConstants.SEPARATOR_BYTE_ARRAY), rs.getBytes(1));
+        assertFalse(rs.next());
+
+        conn.createStatement().execute("CREATE TABLE tdesc (k BINARY(3) PRIMARY KEY DESC)");
+        conn.createStatement().execute("UPSERT INTO tdesc VALUES('a')");
+        conn.createStatement().execute("UPSERT INTO tdesc VALUES('ab')");
+        conn.commit();
+        rs = conn.createStatement().executeQuery("SELECT * FROM tdesc ORDER BY k DESC");
+        assertTrue(rs.next());
+        assertArrayEquals(ByteUtil.concat(Bytes.toBytes("ab"), QueryConstants.SEPARATOR_BYTE_ARRAY), rs.getBytes(1));
+        assertTrue(rs.next());
+        assertArrayEquals(ByteUtil.concat(Bytes.toBytes("a"), QueryConstants.SEPARATOR_BYTE_ARRAY, QueryConstants.SEPARATOR_BYTE_ARRAY), rs.getBytes(1));
         assertFalse(rs.next());
     }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/compile/KeyPart.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/KeyPart.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/KeyPart.java
index 4eb53d3..55385f2 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/KeyPart.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/KeyPart.java
@@ -20,10 +20,10 @@ package org.apache.phoenix.compile;
 import java.util.List;
 
 import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
-
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.query.KeyRange;
 import org.apache.phoenix.schema.PColumn;
+import org.apache.phoenix.schema.PTable;
 
 /**
  * 
@@ -74,4 +74,10 @@ public interface KeyPart {
      * @return the primary key column for this key part
      */
     public PColumn getColumn();
+    
+    /**
+     * Gets the table metadata object associated with this key part
+     * @return the table for this key part
+     */
+    public PTable getTable();
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
index 332f293..a270f12 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
@@ -63,7 +63,7 @@ import org.apache.phoenix.schema.SaltingUtil;
 import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.ValueSchema.Field;
 import org.apache.phoenix.schema.tuple.Tuple;
-import org.apache.phoenix.schema.types.PArrayDataType;
+import org.apache.phoenix.schema.types.PBinary;
 import org.apache.phoenix.schema.types.PChar;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.types.PVarbinary;
@@ -322,6 +322,14 @@ public class WhereOptimizer {
         }
     }
     
+    private static int computeUnpaddedLength(byte[] b, byte padByte) {
+        int len = b.length;
+        while (len > 0 && b[len - 1] == padByte) {
+            len--;
+        }
+        return len;                                       
+    }
+    
     // Special hack for PHOENIX-2067 to change the constant array to match
     // the separators used for descending, variable length arrays.
     // Note that there'd already be a coerce expression around the constant
@@ -335,27 +343,60 @@ public class WhereOptimizer {
             PTable table = context.getCurrentTable().getTable();
             // Constants are always build with rowKeyOptimizable as true, using the correct separators
             // We only need to do this conversion if we have a table that has not yet been converted.
-            if (type != null && type.isArrayType() && column.getSortOrder() == SortOrder.DESC && !PArrayDataType.arrayBaseType(type).isFixedWidth() && !table.rowKeyOrderOptimizable()) {
-                ImmutableBytesWritable ptr = context.getTempPtr();
-                List<KeyRange> newKeyRanges = Lists.newArrayListWithExpectedSize(keyRanges.size());
-                for (KeyRange keyRange : keyRanges) {
-                    byte[] lower = keyRange.getLowerRange();
-                    if (!keyRange.lowerUnbound()) {
-                        ptr.set(lower);;
-                        type.coerceBytes(ptr, null, type, null, null, SortOrder.DESC, null, null, SortOrder.DESC, false);
-                        lower = ByteUtil.copyKeyBytesIfNecessary(ptr);
+            if (type != null && !table.rowKeyOrderOptimizable()) {
+                if (type.isArrayType() && column.getSortOrder() == SortOrder.DESC) {
+                    ImmutableBytesWritable ptr = context.getTempPtr();
+                    List<KeyRange> newKeyRanges = Lists.newArrayListWithExpectedSize(keyRanges.size());
+                    for (KeyRange keyRange : keyRanges) {
+                        byte[] lower = keyRange.getLowerRange();
+                        if (!keyRange.lowerUnbound()) {
+                            ptr.set(lower);
+                            type.coerceBytes(ptr, null, type, null, null, SortOrder.DESC, null, null, SortOrder.DESC, false);
+                            lower = ByteUtil.copyKeyBytesIfNecessary(ptr);
+                        }
+                        byte[] upper = keyRange.getUpperRange();
+                        if (!keyRange.upperUnbound()) {
+                            ptr.set(upper);
+                            type.coerceBytes(ptr, null, type, null, null, SortOrder.DESC, null, null, SortOrder.DESC, false);
+                            upper = ByteUtil.copyKeyBytesIfNecessary(ptr);
+                        }
+                        keyRange = KeyRange.getKeyRange(lower, keyRange.isLowerInclusive(), upper, keyRange.isUpperInclusive());
+                        newKeyRanges.add(keyRange);
                     }
-                    byte[] upper = keyRange.getUpperRange();
-                    if (!keyRange.upperUnbound()) {
-                        ptr.set(upper);;
-                        type.coerceBytes(ptr, null, type, null, null, SortOrder.DESC, null, null, SortOrder.DESC, false);
-                        upper = ByteUtil.copyKeyBytesIfNecessary(ptr);
+                    return newKeyRanges;
+                } else if (type == PBinary.INSTANCE || (column.getSortOrder() == SortOrder.DESC && type == PChar.INSTANCE)) {
+                    // Since the table has not been upgraded, we need to replace the correct trailing byte back to the incorrect
+                    // trailing byte so that we form the correct start/stop key
+                    List<KeyRange> newKeyRanges = Lists.newArrayListWithExpectedSize(keyRanges.size());
+                    byte byteToReplace;
+                    if (type == PBinary.INSTANCE) {
+                        byteToReplace = column.getSortOrder() == SortOrder.ASC ? QueryConstants.SEPARATOR_BYTE : QueryConstants.DESC_SEPARATOR_BYTE;
+                    } else {
+                        byteToReplace = StringUtil.INVERTED_SPACE_UTF8;
+                    }
+                    for (KeyRange keyRange : keyRanges) {
+                        byte[] lower = keyRange.getLowerRange();
+                        if (!keyRange.lowerUnbound()) {
+                            int len = computeUnpaddedLength(lower, byteToReplace);
+                            if (len != lower.length) {
+                                lower = Arrays.copyOf(lower, len);
+                                lower = StringUtil.padChar(lower, lower.length);
+                            }
+                        }
+                        byte[] upper = keyRange.getUpperRange();
+                        if (!keyRange.upperUnbound()) {
+                            int len = computeUnpaddedLength(upper, byteToReplace);
+                            if (len != upper.length) {
+                                upper = Arrays.copyOf(upper, len);
+                                upper = StringUtil.padChar(upper, upper.length);
+                            }
+                        }
+                        keyRange = KeyRange.getKeyRange(lower, keyRange.isLowerInclusive(), upper, keyRange.isUpperInclusive());
+                        newKeyRanges.add(keyRange);
                     }
-                    keyRange = KeyRange.getKeyRange(lower, keyRange.isLowerInclusive(), upper, keyRange.isUpperInclusive());
-                    newKeyRanges.add(keyRange);
+                    return newKeyRanges;
                 }
                 
-                return newKeyRanges;
             }
         }
         return keyRanges;
@@ -532,7 +573,7 @@ public class WhereOptimizer {
             List<Expression> extractNodes = extractNode == null || slot.getKeyPart().getExtractNodes().isEmpty()
                   ? Collections.<Expression>emptyList()
                   : Collections.<Expression>singletonList(extractNode);
-            return new SingleKeySlot(new BaseKeyPart(slot.getKeyPart().getColumn(), extractNodes), slot.getPKPosition(), slot.getPKSpan(), keyRanges, minMaxRange, slot.getOrderPreserving());
+            return new SingleKeySlot(new BaseKeyPart(table, slot.getKeyPart().getColumn(), extractNodes), slot.getPKPosition(), slot.getPKSpan(), keyRanges, minMaxRange, slot.getOrderPreserving());
         }
 
         private KeySlots newKeyParts(KeySlot slot, List<Expression> extractNodes, List<KeyRange> keyRanges, KeyRange minMaxRange) {
@@ -540,7 +581,7 @@ public class WhereOptimizer {
                 return EMPTY_KEY_SLOTS;
             }
             
-            return new SingleKeySlot(new BaseKeyPart(slot.getKeyPart().getColumn(), extractNodes), slot.getPKPosition(), slot.getPKSpan(), keyRanges, minMaxRange, slot.getOrderPreserving());
+            return new SingleKeySlot(new BaseKeyPart(table, slot.getKeyPart().getColumn(), extractNodes), slot.getPKPosition(), slot.getPKSpan(), keyRanges, minMaxRange, slot.getOrderPreserving());
         }
 
         private KeySlots newRowValueConstructorKeyParts(RowValueConstructorExpression rvc, List<KeySlots> childSlots) {
@@ -648,6 +689,11 @@ public class WhereOptimizer {
                 public PColumn getColumn() {
                     return childPart.getColumn();
                 }
+
+                @Override
+                public PTable getTable() {
+                    return childPart.getTable();
+                }
             }, slot.getPKPosition(), slot.getKeyRanges());
         }
 
@@ -724,7 +770,7 @@ public class WhereOptimizer {
 
             if (!minMaxExtractNodes.isEmpty()) {
                 if (keySlot[initPosition] == null) {
-                    keySlot[initPosition] = new KeySlot(new BaseKeyPart(table.getPKColumns().get(initPosition), minMaxExtractNodes), initPosition, 1, EVERYTHING_RANGES, null);
+                    keySlot[initPosition] = new KeySlot(new BaseKeyPart(table, table.getPKColumns().get(initPosition), minMaxExtractNodes), initPosition, 1, EVERYTHING_RANGES, null);
                 } else {
                     keySlot[initPosition] = keySlot[initPosition].concatExtractNodes(minMaxExtractNodes);
                 }
@@ -841,7 +887,7 @@ public class WhereOptimizer {
                 slotRanges = Collections.emptyList();
             }
             if (theSlot == null) {
-                theSlot = new KeySlot(new BaseKeyPart(table.getPKColumns().get(initialPos), slotExtractNodes), initialPos, 1, EVERYTHING_RANGES, null);
+                theSlot = new KeySlot(new BaseKeyPart(table, table.getPKColumns().get(initialPos), slotExtractNodes), initialPos, 1, EVERYTHING_RANGES, null);
             } else if (minMaxRange != KeyRange.EMPTY_RANGE && !slotExtractNodes.isEmpty()) {
                 theSlot = theSlot.concatExtractNodes(slotExtractNodes);
             }
@@ -926,7 +972,7 @@ public class WhereOptimizer {
         @Override
         public KeySlots visit(RowKeyColumnExpression node) {
             PColumn column = table.getPKColumns().get(node.getPosition());
-            return new SingleKeySlot(new BaseKeyPart(column, Collections.<Expression>singletonList(node)), node.getPosition(), 1, EVERYTHING_RANGES);
+            return new SingleKeySlot(new BaseKeyPart(table, column, Collections.<Expression>singletonList(node)), node.getPosition(), 1, EVERYTHING_RANGES);
         }
 
         @Override
@@ -997,7 +1043,8 @@ public class WhereOptimizer {
             KeySlots childSlots = childParts.get(0);
             KeySlot childSlot = childSlots.iterator().next();
             final String startsWith = node.getLiteralPrefix();
-            byte[] key = PVarchar.INSTANCE.toBytes(startsWith, node.getChildren().get(0).getSortOrder());
+            SortOrder sortOrder = node.getChildren().get(0).getSortOrder();
+            byte[] key = PVarchar.INSTANCE.toBytes(startsWith, sortOrder);
             // If the expression is an equality expression against a fixed length column
             // and the key length doesn't match the column length, the expression can
             // never be true.
@@ -1014,8 +1061,15 @@ public class WhereOptimizer {
             byte[] upperRange = ByteUtil.nextKey(key);
             Integer columnFixedLength = column.getMaxLength();
             if (type.isFixedWidth() && columnFixedLength != null) {
-                lowerRange = StringUtil.padChar(lowerRange, columnFixedLength);
-                upperRange = StringUtil.padChar(upperRange, columnFixedLength);
+                if (table.rowKeyOrderOptimizable()) {
+                    // Always use minimum byte to fill as otherwise our key is bigger
+                    // that it should be when the sort order is descending.
+                    lowerRange = type.pad(lowerRange, columnFixedLength, SortOrder.ASC);
+                    upperRange = type.pad(upperRange, columnFixedLength, SortOrder.ASC);
+                } else { // TODO: remove broken logic once tables are required to have been upgraded for PHOENIX-2067 and PHOENIX-2120
+                    lowerRange = StringUtil.padChar(lowerRange, columnFixedLength);
+                    upperRange = StringUtil.padChar(upperRange, columnFixedLength);
+                }
             }
             KeyRange keyRange = type.getKeyRange(lowerRange, true, upperRange, false);
             // Only extract LIKE expression if pattern ends with a wildcard and everything else was extracted
@@ -1117,7 +1171,7 @@ public class WhereOptimizer {
 
             public final KeySlot concatExtractNodes(List<Expression> extractNodes) {
                 return new KeySlot(
-                        new BaseKeyPart(this.getKeyPart().getColumn(),
+                        new BaseKeyPart(this.getKeyPart().getTable(), this.getKeyPart().getColumn(),
                                     SchemaUtil.concat(this.getKeyPart().getExtractNodes(),extractNodes)),
                         this.getPKPosition(),
                         this.getPKSpan(),
@@ -1135,7 +1189,7 @@ public class WhereOptimizer {
                         return null;
                     }
                     return new KeySlot(
-                            new BaseKeyPart(this.getKeyPart().getColumn(),
+                            new BaseKeyPart(this.getKeyPart().getTable(), this.getKeyPart().getColumn(),
                                         SchemaUtil.concat(this.getKeyPart().getExtractNodes(),
                                                           that.getKeyPart().getExtractNodes())),
                             this.getPKPosition(),
@@ -1181,7 +1235,7 @@ public class WhereOptimizer {
                             return null;
                         }
                         return new KeySlot(
-                                new BaseKeyPart(this.getKeyPart().getColumn(),
+                                new BaseKeyPart(this.getKeyPart().getTable(), this.getKeyPart().getColumn(),
                                             SchemaUtil.concat(this.getKeyPart().getExtractNodes(),
                                                               that.getKeyPart().getExtractNodes())),
                                 this.getPKPosition(),
@@ -1272,10 +1326,12 @@ public class WhereOptimizer {
                 return ByteUtil.getKeyRange(key, op, type);
             }
 
+            private final PTable table;
             private final PColumn column;
             private final List<Expression> nodes;
 
-            private BaseKeyPart(PColumn column, List<Expression> nodes) {
+            private BaseKeyPart(PTable table, PColumn column, List<Expression> nodes) {
+                this.table = table;
                 this.column = column;
                 this.nodes = nodes;
             }
@@ -1289,9 +1345,14 @@ public class WhereOptimizer {
             public PColumn getColumn() {
                 return column;
             }
+
+            @Override
+            public PTable getTable() {
+                return table;
+            }
         }
         
-        private  class RowValueConstructorKeyPart implements KeyPart {
+        private class RowValueConstructorKeyPart implements KeyPart {
             private final RowValueConstructorExpression rvc;
             private final PColumn column;
             private final List<Expression> nodes;
@@ -1319,7 +1380,13 @@ public class WhereOptimizer {
             public PColumn getColumn() {
                 return column;
             }
-           @Override
+
+            @Override
+            public PTable getTable() {
+                return table;
+            }
+
+            @Override
             public KeyRange getKeyRange(CompareOp op, Expression rhs) {
                // With row value constructors, we need to convert the operator for any transformation we do on individual values
                // to prevent keys from being increased to the next key as would be done for fixed width values. The next key is
@@ -1446,7 +1513,6 @@ public class WhereOptimizer {
                 byte[] key = ByteUtil.copyKeyBytesIfNecessary(ptr);
                 return ByteUtil.getKeyRange(key, op, PVarbinary.INSTANCE);
             }
-
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
index 788a342..a7e3e44 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
@@ -85,7 +85,8 @@ import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.ValueSchema.Field;
 import org.apache.phoenix.schema.stats.StatisticsCollector;
 import org.apache.phoenix.schema.tuple.MultiKeyValueTuple;
-import org.apache.phoenix.schema.types.PArrayDataType;
+import org.apache.phoenix.schema.types.PBinary;
+import org.apache.phoenix.schema.types.PChar;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.IndexUtil;
@@ -95,6 +96,7 @@ import org.apache.phoenix.util.MetaDataUtil;
 import org.apache.phoenix.util.ScanUtil;
 import org.apache.phoenix.util.SchemaUtil;
 import org.apache.phoenix.util.ServerUtil;
+import org.apache.phoenix.util.StringUtil;
 import org.apache.phoenix.util.TimeKeeper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -296,11 +298,30 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver{
                                         break;
                                     }
                                     Field field = schema.getField(i);
-                                    // Special case for re-writing DESC ARRAY, as the actual byte value needs to change in this case
-                                    if (field.getDataType().isArrayType() && field.getSortOrder() == SortOrder.DESC && !PArrayDataType.arrayBaseType(field.getDataType()).isFixedWidth()) {
-                                        field.getDataType().coerceBytes(ptr, null, field.getDataType(),
-                                                field.getMaxLength(), field.getScale(), field.getSortOrder(), 
-                                                field.getMaxLength(), field.getScale(), field.getSortOrder(), true); // force to use correct separator byte
+                                    if (field.getSortOrder() == SortOrder.DESC) {
+                                        // Special case for re-writing DESC ARRAY, as the actual byte value needs to change in this case
+                                        if (field.getDataType().isArrayType()) {
+                                            field.getDataType().coerceBytes(ptr, null, field.getDataType(),
+                                                    field.getMaxLength(), field.getScale(), field.getSortOrder(), 
+                                                    field.getMaxLength(), field.getScale(), field.getSortOrder(), true); // force to use correct separator byte
+                                        }
+                                        // Special case for re-writing DESC CHAR or DESC BINARY, to force the re-writing of trailing space characters
+                                        else if (field.getDataType() == PChar.INSTANCE || field.getDataType() == PBinary.INSTANCE) {
+                                            int len = ptr.getLength();
+                                            while (len > 0 && ptr.get()[ptr.getOffset() + len - 1] == StringUtil.SPACE_UTF8) {
+                                                len--;
+                                            }
+                                            ptr.set(ptr.get(), ptr.getOffset(), len);
+                                        }
+                                    } else if (field.getDataType() == PBinary.INSTANCE) {
+                                        // Remove trailing space characters so that the setValues call below will replace them
+                                        // with the correct zero byte character. Note this is somewhat dangerous as these
+                                        // could be legit, but I don't know what the alternative is.
+                                        int len = ptr.getLength();
+                                        while (len > 0 && ptr.get()[ptr.getOffset() + len - 1] == StringUtil.SPACE_UTF8) {
+                                            len--;
+                                        }
+                                        ptr.set(ptr.get(), ptr.getOffset(), len);                                        
                                     }
                                     values[i] = ptr.copyBytes();
                                 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/expression/LiteralExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/LiteralExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/LiteralExpression.java
index 26c076c..c1faf66 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/LiteralExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/LiteralExpression.java
@@ -37,7 +37,6 @@ import org.apache.phoenix.schema.types.PTimestamp;
 import org.apache.phoenix.schema.types.PVarchar;
 import org.apache.phoenix.schema.types.PhoenixArray;
 import org.apache.phoenix.util.ByteUtil;
-import org.apache.phoenix.util.StringUtil;
 
 import com.google.common.base.Preconditions;
 
@@ -174,7 +173,7 @@ public class LiteralExpression extends BaseTerminalExpression {
         byte[] b = type.toBytes(value, sortOrder);
         if (type == PVarchar.INSTANCE || type == PChar.INSTANCE) {
             if (type == PChar.INSTANCE && maxLength != null  && b.length < maxLength) {
-                b = StringUtil.padChar(b, maxLength);
+                b = type.pad(b, maxLength, sortOrder);
             } else if (value != null) {
                 maxLength = ((String)value).length();
             }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InvertFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InvertFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InvertFunction.java
index 3dcbf7c..6a3e2a1 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InvertFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InvertFunction.java
@@ -28,9 +28,10 @@ import org.apache.phoenix.parse.FunctionParseNode.Argument;
 import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
 import org.apache.phoenix.query.KeyRange;
 import org.apache.phoenix.schema.PColumn;
-import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.PTable;
 import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.PDataType;
 
 @BuiltInFunction(name = InvertFunction.NAME, args = { @Argument() })
 public class InvertFunction extends ScalarFunction {
@@ -107,6 +108,11 @@ public class InvertFunction extends ScalarFunction {
             public PColumn getColumn() {
                 return childPart.getColumn();
             }
+
+            @Override
+            public PTable getTable() {
+                return childPart.getTable();
+            }
         };
     }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PrefixFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PrefixFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PrefixFunction.java
index 3373df7..111c8b3 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PrefixFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PrefixFunction.java
@@ -26,9 +26,10 @@ import org.apache.phoenix.compile.KeyPart;
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.query.KeyRange;
 import org.apache.phoenix.schema.PColumn;
+import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.util.ByteUtil;
-import org.apache.phoenix.util.StringUtil;
 
 abstract public class PrefixFunction extends ScalarFunction {
     public PrefixFunction() {
@@ -84,16 +85,22 @@ abstract public class PrefixFunction extends ScalarFunction {
                     return childPart.getKeyRange(op, rhs);
                 }
                 Integer length = getColumn().getMaxLength();
+                SortOrder sortOrder = getColumn().getSortOrder();
                 if (type.isFixedWidth() && length != null) {
                     if (lowerRange != KeyRange.UNBOUND) {
-                        lowerRange = StringUtil.padChar(lowerRange, length);
+                        lowerRange = type.pad(lowerRange, length, sortOrder);
                     }
                     if (upperRange != KeyRange.UNBOUND) {
-                        upperRange = StringUtil.padChar(upperRange, length);
+                        upperRange = type.pad(upperRange, length, sortOrder);
                     }
                 }
                 return KeyRange.getKeyRange(lowerRange, lowerInclusive, upperRange, false);
             }
+
+            @Override
+            public PTable getTable() {
+                return childPart.getTable();
+            }
         };
     }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RTrimFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RTrimFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RTrimFunction.java
index 911ed19..aa632e2 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RTrimFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RTrimFunction.java
@@ -29,10 +29,11 @@ import org.apache.phoenix.parse.FunctionParseNode.Argument;
 import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
 import org.apache.phoenix.query.KeyRange;
 import org.apache.phoenix.schema.PColumn;
-import org.apache.phoenix.schema.types.PDataType;
-import org.apache.phoenix.schema.types.PVarchar;
+import org.apache.phoenix.schema.PTable;
 import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PVarchar;
 import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.StringUtil;
 
@@ -123,12 +124,13 @@ public class RTrimFunction extends ScalarFunction {
                     return childPart.getKeyRange(op, rhs);
                 }
                 Integer length = getColumn().getMaxLength();
+                SortOrder sortOrder = getColumn().getSortOrder();
                 if (type.isFixedWidth() && length != null) {
                     if (lowerRange != KeyRange.UNBOUND) {
-                        lowerRange = StringUtil.padChar(lowerRange, length);
+                        lowerRange = type.pad(lowerRange, length, sortOrder);
                     }
                     if (upperRange != KeyRange.UNBOUND) {
-                        upperRange = StringUtil.padChar(upperRange, length);
+                        upperRange = type.pad(upperRange, length, sortOrder);
                     }
                 }
                 return KeyRange.getKeyRange(lowerRange, lowerInclusive, upperRange, false);
@@ -143,6 +145,11 @@ public class RTrimFunction extends ScalarFunction {
             public PColumn getColumn() {
                 return childPart.getColumn();
             }
+
+            @Override
+            public PTable getTable() {
+                return childPart.getTable();
+            }
         };
     }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDateExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDateExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDateExpression.java
index d8fa1dc..e410e34 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDateExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDateExpression.java
@@ -33,13 +33,14 @@ import org.apache.phoenix.expression.Determinism;
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.expression.LiteralExpression;
 import org.apache.phoenix.query.KeyRange;
-import org.apache.phoenix.schema.types.PInteger;
 import org.apache.phoenix.schema.PColumn;
+import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.tuple.Tuple;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.types.PDataType.PDataCodec;
+import org.apache.phoenix.schema.types.PInteger;
 import org.apache.phoenix.schema.types.PVarchar;
-import org.apache.phoenix.schema.SortOrder;
-import org.apache.phoenix.schema.tuple.Tuple;
 import org.apache.phoenix.util.ByteUtil;
 
 import com.google.common.collect.Lists;
@@ -255,6 +256,11 @@ public class RoundDateExpression extends ScalarFunction {
                     return childPart.getKeyRange(op, rhs);
                 }
             }
+
+            @Override
+            public PTable getTable() {
+                return childPart.getTable();
+            }
         };
     }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDecimalExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDecimalExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDecimalExpression.java
index e81650f..7f44082 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDecimalExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDecimalExpression.java
@@ -23,26 +23,27 @@ import java.io.IOException;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.sql.SQLException;
+import java.util.Collections;
 import java.util.List;
 
+import org.apache.hadoop.hbase.filter.CompareFilter;
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.hadoop.io.WritableUtils;
+import org.apache.phoenix.compile.KeyPart;
 import org.apache.phoenix.expression.Determinism;
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.expression.LiteralExpression;
-import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.query.KeyRange;
 import org.apache.phoenix.schema.IllegalDataException;
-import org.apache.phoenix.schema.types.PInteger;
+import org.apache.phoenix.schema.PColumn;
+import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.tuple.Tuple;
 import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.types.PInteger;
 import org.apache.phoenix.schema.types.PLong;
-import org.apache.phoenix.schema.tuple.Tuple;
 
 import com.google.common.collect.Lists;
-import java.util.Collections;
-import org.apache.hadoop.hbase.filter.CompareFilter;
-import org.apache.phoenix.compile.KeyPart;
-import org.apache.phoenix.query.KeyRange;
-import org.apache.phoenix.schema.PColumn;
 
 /**
  *
@@ -274,6 +275,11 @@ public class RoundDecimalExpression extends ScalarFunction {
                 // otherwise, rounding has not affected the operator, so return normally
                 return rounded;
             }
+
+            @Override
+            public PTable getTable() {
+                return childPart.getTable();
+            }
         };
     }
     

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
index a17e28a..dede98d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
@@ -1983,9 +1983,13 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
                                     props.remove(PhoenixRuntime.TENANT_ID_ATTRIB);
                                     PhoenixConnection conn = new PhoenixConnection(ConnectionQueryServicesImpl.this, metaConnection.getURL(), props, metaConnection.getMetaDataCache());
                                     try {
-                                        Set<String> tablesNeedingUpgrade = UpgradeUtil.getPhysicalTablesWithDescVarLengthRowKey(conn);
+                                        List<String> tablesNeedingUpgrade = UpgradeUtil.getPhysicalTablesWithDescRowKey(conn);
                                         if (!tablesNeedingUpgrade.isEmpty()) {
-                                            logger.warn("The following tables require upgrade due to a bug causing the row key to be incorrect for descending columns (PHOENIX-2067):\n" + Joiner.on(' ').join(tablesNeedingUpgrade));
+                                            logger.warn("The following tables require upgrade due to a bug causing the row key to be incorrect for descending columns and ascending BINARY columns (PHOENIX-2067 and PHOENIX-2120):\n" + Joiner.on(' ').join(tablesNeedingUpgrade) + "\nTo upgrade issue the \"bin/psql.py -u\" command.");
+                                        }
+                                        List<String> unsupportedTables = UpgradeUtil.getPhysicalTablesWithDescVarbinaryRowKey(conn);
+                                        if (!unsupportedTables.isEmpty()) {
+                                            logger.warn("The following tables use an unsupported VARBINARY DESC construct and need to be changed:\n" + Joiner.on(' ').join(unsupportedTables));
                                         }
                                     } catch (Exception ex) {
                                         logger.error("Unable to determine tables requiring upgrade due to PHOENIX-2067", ex);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
index 1756c2f..521fb42 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
@@ -54,6 +54,8 @@ import org.apache.phoenix.schema.RowKeySchema.RowKeySchemaBuilder;
 import org.apache.phoenix.schema.stats.GuidePostsInfo;
 import org.apache.phoenix.schema.stats.PTableStats;
 import org.apache.phoenix.schema.stats.PTableStatsImpl;
+import org.apache.phoenix.schema.types.PBinary;
+import org.apache.phoenix.schema.types.PChar;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.types.PVarchar;
 import org.apache.phoenix.util.ByteUtil;
@@ -125,8 +127,8 @@ public class PTableImpl implements PTable {
     private IndexType indexType;
     private PTableStats tableStats = PTableStats.EMPTY_STATS;
     private int baseColumnCount;
-    private boolean hasDescVarLengthColumns;
-    private boolean rowKeyOrderOptimizable;
+    private boolean rowKeyOrderOptimizable; // TODO: remove when required that tables have been upgrade for PHOENIX-2067
+    private boolean hasColumnsRequiringUpgrade; // TODO: remove when required that tables have been upgrade for PHOENIX-2067
 
     public PTableImpl() {
         this.indexes = Collections.emptyList();
@@ -405,7 +407,8 @@ public class PTableImpl implements PTable {
         for (PColumn column : allColumns) {
             PName familyName = column.getFamilyName();
             if (familyName == null) {
-                hasDescVarLengthColumns |= (column.getSortOrder() == SortOrder.DESC && !column.getDataType().isFixedWidth());
+                hasColumnsRequiringUpgrade |= (column.getSortOrder() == SortOrder.DESC && (!column.getDataType().isFixedWidth() || column.getDataType() == PChar.INSTANCE || column.getDataType() == PBinary.INSTANCE))
+                        || (column.getSortOrder() == SortOrder.ASC && column.getDataType() == PBinary.INSTANCE && column.getMaxLength() != null && column.getMaxLength() > 1);
             	pkColumns.add(column);
             }
             if (familyName == null) {
@@ -547,8 +550,16 @@ public class PTableImpl implements PTable {
                     throw new ConstraintViolationException(name.getString() + "." + column.getName().getString() + " may not be null");
                 }
                 Integer	maxLength = column.getMaxLength();
-                if (maxLength != null && type.isFixedWidth() && byteValue.length <= maxLength) {
-                    byteValue = StringUtil.padChar(byteValue, maxLength);
+                if (maxLength != null && type.isFixedWidth() && byteValue.length < maxLength) {
+                    if (rowKeyOrderOptimizable()) {
+                        key.set(byteValue);
+                        type.pad(key, maxLength, sortOrder);
+                        byteValue = ByteUtil.copyKeyBytesIfNecessary(key);
+                    } else {
+                        // TODO: remove this incorrect code and move StringUtil.padChar() to TestUtil
+                        // once we require tables to have been upgraded
+                        byteValue = StringUtil.padChar(byteValue, maxLength);
+                    }
                 } else if (maxLength != null && byteValue.length > maxLength) {
                     throw new DataExceedsCapacityException(name.getString() + "." + column.getName().getString() + " may not exceed " + maxLength + " bytes (" + SchemaUtil.toString(type, byteValue) + ")");
                 }
@@ -733,7 +744,7 @@ public class PTableImpl implements PTable {
                         HConstants.EMPTY_BYTE_ARRAY : byteValue);
                 Integer	maxLength = column.getMaxLength();
             	if (!isNull && type.isFixedWidth() && maxLength != null) {
-    				if (ptr.getLength() <= maxLength) {
+    				if (ptr.getLength() < maxLength) {
                         type.pad(ptr, maxLength, column.getSortOrder());
                     } else if (ptr.getLength() > maxLength) {
                         throw new DataExceedsCapacityException(name.getString() + "." + column.getName().getString() + " may not exceed " + maxLength + " bytes (" + type.toObject(byteValue) + ")");
@@ -1131,6 +1142,6 @@ public class PTableImpl implements PTable {
 
     @Override
     public boolean rowKeyOrderOptimizable() {
-        return rowKeyOrderOptimizable || !hasDescVarLengthColumns;
+        return rowKeyOrderOptimizable || !hasColumnsRequiringUpgrade;
     }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinary.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinary.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinary.java
index b397554..8e0c4b5 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinary.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinary.java
@@ -19,11 +19,13 @@ package org.apache.phoenix.schema.types;
 
 import java.sql.Types;
 import java.text.Format;
+import java.util.Arrays;
 
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.hadoop.hbase.util.Base64;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.phoenix.exception.DataExceedsCapacityException;
+import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.schema.SortOrder;
 
 public class PBinary extends PDataType<byte[]> {
@@ -35,29 +37,43 @@ public class PBinary extends PDataType<byte[]> {
   }
 
   @Override
+  public byte[] pad(byte[] b, Integer maxLength, SortOrder sortOrder) {
+      if (b == null || b.length >= maxLength) {
+          return b;
+        }
+        byte[] newBytes = new byte[maxLength];
+        System.arraycopy(b, 0, newBytes, 0, b.length);
+        if (sortOrder == SortOrder.DESC) {
+            Arrays.fill(newBytes, b.length, maxLength, QueryConstants.DESC_SEPARATOR_BYTE);
+        }
+        return newBytes;
+  }
+  
+  @Override
   public void pad(ImmutableBytesWritable ptr, Integer maxLength, SortOrder sortOrder) {
     if (ptr.getLength() >= maxLength) {
       return;
     }
     byte[] newBytes = new byte[maxLength];
     System.arraycopy(ptr.get(), ptr.getOffset(), newBytes, 0, ptr.getLength());
+    if (sortOrder == SortOrder.DESC) {
+        Arrays.fill(newBytes, ptr.getLength(), maxLength, QueryConstants.DESC_SEPARATOR_BYTE);
+    }
     ptr.set(newBytes);
   }
 
   @Override
   public Object pad(Object object, Integer maxLength) {
     byte[] b = (byte[]) object;
-    if (b == null) {
-      return new byte[maxLength];
-    }
-    if (b.length == maxLength) {
+    int length = (b == null ? 0 : b.length);
+    if (length == maxLength) {
       return object;
     }
-    if (b.length > maxLength) {
+    if (length > maxLength) {
       throw new DataExceedsCapacityException(this, maxLength, null);
     }
     byte[] newBytes = new byte[maxLength];
-    System.arraycopy(b, 0, newBytes, 0, b.length);
+    System.arraycopy(b, 0, newBytes, 0, length);
 
     return newBytes;
   }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PChar.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PChar.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PChar.java
index c7cc1c1..6b26197 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PChar.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PChar.java
@@ -53,6 +53,17 @@ public class PChar extends PDataType<String> {
     }
 
     @Override
+    public byte[] pad(byte[] b, Integer maxLength, SortOrder sortOrder) {
+      if (b == null || b.length >= maxLength) {
+        return b;
+      }
+      byte[] newBytes = new byte[maxLength];
+      System.arraycopy(b, 0, newBytes, 0, b.length);
+      Arrays.fill(newBytes, b.length, maxLength, sortOrder == SortOrder.ASC ? StringUtil.SPACE_UTF8 : StringUtil.INVERTED_SPACE_UTF8);
+      return newBytes;
+    }
+
+    @Override
     public Object pad(Object object, Integer maxLength) {
       String s = (String) object;
       if (s == null) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
index 2c91dc5..43bab0e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
@@ -1147,6 +1147,7 @@ public abstract class PDataType<T> implements DataType<T>, Comparable<PDataType<
     }
 
     public void pad(ImmutableBytesWritable ptr, Integer maxLength, SortOrder sortOrder) {}
+    public byte[] pad(byte[] b, Integer maxLength, SortOrder sortOrder) { return b; }
 
     public static PDataType arrayBaseType(PDataType arrayType) {
         Preconditions.checkArgument(arrayType.isArrayType(), "Not a phoenix array type");

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java b/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
index 1a2019d..c99d47e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
@@ -193,17 +193,28 @@ public class PhoenixRuntime {
                     .unwrap(PhoenixConnection.class);
 
             if (execCmd.isUpgrade()) {
+                if (conn.getClientInfo(PhoenixRuntime.CURRENT_SCN_ATTRIB) != null) {
+                    throw new SQLException("May not specify the CURRENT_SCN property when upgrading");
+                }
+                if (conn.getClientInfo(PhoenixRuntime.TENANT_ID_ATTRIB) != null) {
+                    throw new SQLException("May not specify the TENANT_ID_ATTRIB property when upgrading");
+                }
                 if (execCmd.getInputFiles().isEmpty()) {
-                    Set<String> tablesNeedingUpgrade = UpgradeUtil.getPhysicalTablesWithDescVarLengthRowKey(conn);
+                    List<String> tablesNeedingUpgrade = UpgradeUtil.getPhysicalTablesWithDescRowKey(conn);
                     if (tablesNeedingUpgrade.isEmpty()) {
-                        String msg = "No tables are required to be upgraded due to incorrect row key order for descending, variable length columsn (PHOENIX-2067)";
+                        String msg = "No tables are required to be upgraded due to incorrect row key order (PHOENIX-2067 and PHOENIX-2120)";
                         System.out.println(msg);
                     } else {
-                        String msg = "The following tables require upgrade due to a bug causing the row key to be incorrect for descending columns (PHOENIX-2067):\n" + Joiner.on(' ').join(tablesNeedingUpgrade);
+                        String msg = "The following tables require upgrade due to a bug causing the row key to be incorrectly ordered (PHOENIX-2067 and PHOENIX-2120):\n" + Joiner.on(' ').join(tablesNeedingUpgrade);
+                        System.out.println("WARNING: " + msg);
+                    }
+                    List<String> unsupportedTables = UpgradeUtil.getPhysicalTablesWithDescVarbinaryRowKey(conn);
+                    if (!unsupportedTables.isEmpty()) {
+                        String msg = "The following tables use an unsupported VARBINARY DESC construct and need to be changed:\n" + Joiner.on(' ').join(unsupportedTables);
                         System.out.println("WARNING: " + msg);
                     }
                 } else {
-                    UpgradeUtil.upgradeDescVarLengthRowKeys(conn, execCmd.getInputFiles());
+                    UpgradeUtil.upgradeDescVarLengthRowKeys(conn, execCmd.getInputFiles(), execCmd.isBypassUpgrade());
                 }
             } else {
                 for (String inputFile : execCmd.getInputFiles()) {
@@ -476,6 +487,7 @@ public class PhoenixRuntime {
         private boolean strict;
         private List<String> inputFiles;
         private boolean isUpgrade;
+        private boolean isBypassUpgrade;
 
         /**
          * Factory method to build up an {@code ExecutionCommand} based on supplied parameters.
@@ -502,9 +514,18 @@ public class PhoenixRuntime {
                     "Define the array element separator, defaults to ':'");
             Option upgradeOption = new Option("u", "upgrade", false, "Upgrades tables specified as arguments " +
                     "by rewriting them with the correct row key for descending columns. If no arguments are " +
-                    "specified, then tables that need to be upgraded will be displayed. " +
+                    "specified, then tables that need to be upgraded will be displayed without being upgraded. " +
+                    "Use the -b option to bypass the rewrite if you know that your data does not need to be upgrade. " +
+                    "This would only be the case if you have not relied on auto padding for BINARY and CHAR data, " +
+                    "but instead have always provided data up to the full max length of the column. See PHOENIX-2067 " +
+                    "and PHOENIX-2120 for more information. " +
                     "Note that " + QueryServices.THREAD_TIMEOUT_MS_ATTRIB + " and hbase.regionserver.lease.period " +
                     "parameters must be set very high to prevent timeouts when upgrading.");
+            Option bypassUpgradeOption = new Option("b", "bypass-upgrade", false,
+                    "Used in conjunction with the -u option to bypass the rewrite during upgrade if you know that your data does not need to be upgrade. " +
+                    "This would only be the case if you have not relied on auto padding for BINARY and CHAR data, " +
+                    "but instead have always provided data up to the full max length of the column. See PHOENIX-2067 " +
+                    "and PHOENIX-2120 for more information. ");
             Options options = new Options();
             options.addOption(tableOption);
             options.addOption(headerOption);
@@ -514,6 +535,7 @@ public class PhoenixRuntime {
             options.addOption(escapeCharacterOption);
             options.addOption(arrayValueSeparatorOption);
             options.addOption(upgradeOption);
+            options.addOption(bypassUpgradeOption);
 
             CommandLineParser parser = new PosixParser();
             CommandLine cmdLine = null;
@@ -558,6 +580,13 @@ public class PhoenixRuntime {
                 execCmd.isUpgrade = true;
             }
 
+            if (cmdLine.hasOption(bypassUpgradeOption.getOpt())) {
+                if (!execCmd.isUpgrade()) {
+                    usageError("The bypass-upgrade option may only be used in conjunction with the -u option", options);
+                }
+                execCmd.isBypassUpgrade = true;
+            }
+
 
             List<String> argList = Lists.newArrayList(cmdLine.getArgList());
             if (argList.isEmpty()) {
@@ -649,6 +678,10 @@ public class PhoenixRuntime {
         public boolean isUpgrade() {
             return isUpgrade;
         }
+
+        public boolean isBypassUpgrade() {
+            return isBypassUpgrade;
+        }
     }
     
     /**

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/util/StringUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/StringUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/StringUtil.java
index 89ae43b..4d3a36f 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/StringUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/StringUtil.java
@@ -268,13 +268,6 @@ public class StringUtil {
         return getFirstNonBlankCharIdxFromEnd(b, offset, length, sortOrder) - offset + 1;
     }
 
-    public static byte[] padChar(byte[] value, int offset, int length, int paddedLength) {
-        byte[] key = new byte[paddedLength];
-        System.arraycopy(value,offset, key, 0, length);
-        Arrays.fill(key, length, paddedLength, SPACE_UTF8);
-        return key;
-    }
-
     public static byte[] padChar(byte[] value, Integer byteSize) {
         byte[] newValue = Arrays.copyOf(value, byteSize);
         if (newValue.length > value.length) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/dcf845c2/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
index b4fcef8..2ab4f8b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
@@ -79,11 +79,14 @@ import org.apache.phoenix.schema.PTable.LinkType;
 import org.apache.phoenix.schema.PTableType;
 import org.apache.phoenix.schema.SaltingUtil;
 import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.types.PBinary;
 import org.apache.phoenix.schema.types.PBoolean;
+import org.apache.phoenix.schema.types.PChar;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.types.PDecimal;
 import org.apache.phoenix.schema.types.PInteger;
 import org.apache.phoenix.schema.types.PLong;
+import org.apache.phoenix.schema.types.PVarbinary;
 import org.apache.phoenix.schema.types.PVarchar;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -878,10 +881,17 @@ public class UpgradeUtil {
         return otherTables;
     }
     
-    // Return all types that are not fixed width that may need upgrading due to PHOENIX-2067
+    // Return all types that are descending and either:
+    // 1) variable length, which includes all array types (PHOENIX-2067)
+    // 2) fixed length with padding (PHOENIX-2120)
     // We exclude VARBINARY as we no longer support DESC for it.
     private static String getAffectedDataTypes() {
-        StringBuilder buf = new StringBuilder("(" + PVarchar.INSTANCE.getSqlType() + "," + PDecimal.INSTANCE.getSqlType() + ",");
+        StringBuilder buf = new StringBuilder("(" 
+                + PVarchar.INSTANCE.getSqlType() + "," +
+                + PChar.INSTANCE.getSqlType() + "," +
+                + PBinary.INSTANCE.getSqlType() + "," +
+                + PDecimal.INSTANCE.getSqlType() + ","
+                );
         for (PDataType type : PDataType.values()) {
             if (type.isArrayType()) {
                 buf.append(type.getSqlType());
@@ -891,20 +901,46 @@ public class UpgradeUtil {
         buf.setCharAt(buf.length()-1, ')');
         return buf.toString();
     }
+    
+    
     /**
-     * Identify the tables that need to be upgraded due to PHOENIX-2067
+     * Identify the tables that are DESC VARBINARY as this is no longer supported
      */
-    public static Set<String> getPhysicalTablesWithDescVarLengthRowKey(PhoenixConnection conn) throws SQLException {
-        // First query finds column rows of tables that need to be upgraded.
-        // We cannot tell if the column is from a table, view, or index however.
-        ResultSet rs = conn.createStatement().executeQuery(
-                "SELECT TENANT_ID,TABLE_SCHEM,TABLE_NAME\n" + 
+    public static List<String> getPhysicalTablesWithDescVarbinaryRowKey(PhoenixConnection conn) throws SQLException {
+        String query = "SELECT TENANT_ID,TABLE_SCHEM,TABLE_NAME\n" + 
                 "FROM SYSTEM.CATALOG cat1\n" + 
                 "WHERE COLUMN_NAME IS NOT NULL\n" + 
                 "AND COLUMN_FAMILY IS NULL\n" + 
                 "AND SORT_ORDER = " + SortOrder.DESC.getSystemValue() + "\n" + 
-                "AND DATA_TYPE IN " + getAffectedDataTypes() + "\n" +
-                "GROUP BY TENANT_ID,TABLE_SCHEM,TABLE_NAME");
+                "AND DATA_TYPE = " + PVarbinary.INSTANCE.getSqlType() + "\n" +
+                "GROUP BY TENANT_ID,TABLE_SCHEM,TABLE_NAME";
+        return getPhysicalTablesWithDescRowKey(query, conn);
+    }
+    
+    /**
+     * Identify the tables that need to be upgraded due to PHOENIX-2067 and PHOENIX-2120
+     */
+    public static List<String> getPhysicalTablesWithDescRowKey(PhoenixConnection conn) throws SQLException {
+        String query = "SELECT TENANT_ID,TABLE_SCHEM,TABLE_NAME\n" + 
+                "FROM SYSTEM.CATALOG cat1\n" + 
+                "WHERE COLUMN_NAME IS NOT NULL\n" + 
+                "AND COLUMN_FAMILY IS NULL\n" + 
+                "AND ( ( SORT_ORDER = " + SortOrder.DESC.getSystemValue() + "\n" + 
+                "        AND DATA_TYPE IN " + getAffectedDataTypes() + ")\n" +
+                "    OR ( SORT_ORDER = " + SortOrder.ASC.getSystemValue() + "\n" + 
+                "         AND DATA_TYPE = " + PBinary.INSTANCE.getSqlType() + "\n" +
+                "         AND COLUMN_SIZE > 1 ) )\n" +
+                "GROUP BY TENANT_ID,TABLE_SCHEM,TABLE_NAME";
+        return getPhysicalTablesWithDescRowKey(query, conn);
+    }
+    
+    /**
+     * Identify the tables that need to be upgraded due to PHOENIX-2067
+     */
+    private static List<String> getPhysicalTablesWithDescRowKey(String query, PhoenixConnection conn) throws SQLException {
+        // First query finds column rows of tables that need to be upgraded.
+        // We cannot tell if the column is from a table, view, or index however.
+        ResultSet rs = conn.createStatement().executeQuery(query);
         Set<String> physicalTables = Sets.newHashSetWithExpectedSize(1024);
         List<String> remainingTableNames = addPhysicalTables(conn, rs, PTableType.INDEX, physicalTables);
         if (!remainingTableNames.isEmpty()) {
@@ -931,71 +967,129 @@ public class UpgradeUtil {
                  addPhysicalTables(conn, rs, PTableType.TABLE, physicalTables);
              }
         }
-        return physicalTables;
+        List<String> sortedPhysicalTables = new ArrayList<String>(physicalTables);
+        Collections.sort(sortedPhysicalTables);
+        return sortedPhysicalTables;
     }
 
-    private static void upgradeDescVarLengthRowKeys(PhoenixConnection upgradeConn, PhoenixConnection globalConn, String schemaName, String tableName, boolean isTable) throws SQLException {
-        String escapedTableName = SchemaUtil.getEscapedTableName(schemaName, tableName);
-        String tenantInfo = "";
-        PName tenantId = PName.EMPTY_NAME;
-        if (upgradeConn.getTenantId() != null) {
-            tenantId = upgradeConn.getTenantId();
-            tenantInfo = " for tenant " + tenantId.getString();
+    private static void upgradeDescVarLengthRowKeys(PhoenixConnection upgradeConn, PhoenixConnection globalConn, String schemaName, String tableName, boolean isTable, boolean bypassUpgrade) throws SQLException {
+        String physicalName = SchemaUtil.getTableName(schemaName, tableName);
+        long currentTime = System.currentTimeMillis();
+        String snapshotName = physicalName + "_" + currentTime;
+        HBaseAdmin admin = null;
+        if (isTable && !bypassUpgrade) {
+            admin = globalConn.getQueryServices().getAdmin();
         }
-        String msg = "Starting upgrade of " + escapedTableName + tenantInfo + "...";
-        System.out.println(msg);
-        logger.info(msg);
-        ResultSet rs = upgradeConn.createStatement().executeQuery("SELECT /*+ NO_INDEX */ count(*) FROM " + escapedTableName);
-        rs.next(); // Run query
-        List<String> tableNames = Lists.newArrayListWithExpectedSize(1024);
-        tableNames.add(tenantId == PName.EMPTY_NAME ? null : tenantId.getString());
-        tableNames.add(schemaName);
-        tableNames.add(tableName);
-        // Find views to mark as upgraded
-        if (isTable) {
-            String physicalName = SchemaUtil.getTableName(schemaName, tableName);
-            String query =
-                    "SELECT TENANT_ID,TABLE_SCHEM,TABLE_NAME\n" + 
-                    "FROM SYSTEM.CATALOG\n" + 
-                    "WHERE COLUMN_NAME IS NULL\n" + 
-                    "AND COLUMN_FAMILY = '" + physicalName + "'" +
-                    "AND LINK_TYPE = " + LinkType.PHYSICAL_TABLE.getSerializedValue();
-            rs = globalConn.createStatement().executeQuery(query);
-            while (rs.next()) {
-                tableNames.add(rs.getString(1));
-                tableNames.add(rs.getString(2));
-                tableNames.add(rs.getString(3));
+        boolean restoreSnapshot = false;
+        boolean success = false;
+        try {
+            if (isTable && !bypassUpgrade) {
+                String msg = "Taking snapshot of physical table " + physicalName + " prior to upgrade...";
+                System.out.println(msg);
+                logger.info(msg);
+                admin.disableTable(physicalName);
+                admin.snapshot(snapshotName, physicalName);
+                admin.enableTable(physicalName);
+                restoreSnapshot = true;
+            }
+            String escapedTableName = SchemaUtil.getEscapedTableName(schemaName, tableName);
+            String tenantInfo = "";
+            PName tenantId = PName.EMPTY_NAME;
+            if (upgradeConn.getTenantId() != null) {
+                tenantId = upgradeConn.getTenantId();
+                tenantInfo = " for tenant " + tenantId.getString();
+            }
+            String msg = "Starting upgrade of " + escapedTableName + tenantInfo + "...";
+            System.out.println(msg);
+            logger.info(msg);
+            ResultSet rs;
+            if (!bypassUpgrade) {
+                rs = upgradeConn.createStatement().executeQuery("SELECT /*+ NO_INDEX */ count(*) FROM " + escapedTableName);
+                rs.next(); // Run query
+            }
+            List<String> tableNames = Lists.newArrayListWithExpectedSize(1024);
+            tableNames.add(tenantId == PName.EMPTY_NAME ? null : tenantId.getString());
+            tableNames.add(schemaName);
+            tableNames.add(tableName);
+            // Find views to mark as upgraded
+            if (isTable) {
+                String query =
+                        "SELECT TENANT_ID,TABLE_SCHEM,TABLE_NAME\n" + 
+                        "FROM SYSTEM.CATALOG\n" + 
+                        "WHERE COLUMN_NAME IS NULL\n" + 
+                        "AND COLUMN_FAMILY = '" + physicalName + "'" +
+                        "AND LINK_TYPE = " + LinkType.PHYSICAL_TABLE.getSerializedValue();
+                rs = globalConn.createStatement().executeQuery(query);
+                while (rs.next()) {
+                    tableNames.add(rs.getString(1));
+                    tableNames.add(rs.getString(2));
+                    tableNames.add(rs.getString(3));
+                }
+            }
+            // Mark the table and views as upgraded now
+            for (int i = 0; i < tableNames.size(); i += 3) {
+                String theTenantId = tableNames.get(i);
+                String theSchemaName = tableNames.get(i+1);
+                String theTableName = tableNames.get(i+2);
+                globalConn.createStatement().execute("UPSERT INTO " + PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME + 
+                    " (" + PhoenixDatabaseMetaData.TENANT_ID + "," +
+                           PhoenixDatabaseMetaData.TABLE_SCHEM + "," +
+                           PhoenixDatabaseMetaData.TABLE_NAME + "," +
+                           MetaDataEndpointImpl.ROW_KEY_ORDER_OPTIMIZABLE + " BOOLEAN"
+                   + ") VALUES (" +
+                           "'" + (theTenantId == null ? StringUtil.EMPTY_STRING : theTenantId) + "'," +
+                           "'" + (theSchemaName == null ? StringUtil.EMPTY_STRING : theSchemaName) + "'," +
+                           "'" + theTableName + "'," +
+                           "TRUE)");
+            }
+            globalConn.commit();
+            for (int i = 0; i < tableNames.size(); i += 3) {
+                String theTenantId = tableNames.get(i);
+                String theSchemaName = tableNames.get(i+1);
+                String theTableName = tableNames.get(i+2);
+                globalConn.getQueryServices().clearTableFromCache(
+                        theTenantId == null ? ByteUtil.EMPTY_BYTE_ARRAY : Bytes.toBytes(theTenantId),
+                        theSchemaName == null ? ByteUtil.EMPTY_BYTE_ARRAY : Bytes.toBytes(schemaName),
+                        Bytes.toBytes(theTableName), HConstants.LATEST_TIMESTAMP);
+            }
+            success = true;
+            msg = "Completed upgrade of " + escapedTableName + tenantInfo;
+            System.out.println(msg);
+            logger.info(msg);
+        } catch (Exception e) {
+            logger.error("Exception during upgrade of " + physicalName + ":", e);
+        } finally {
+            boolean restored = false;
+            try {
+                if (!success && restoreSnapshot) {
+                    admin.disableTable(physicalName);
+                    admin.restoreSnapshot(snapshotName, false);
+                    admin.enableTable(physicalName);
+                    String msg = "Restored snapshot of " + physicalName + " due to failure of upgrade";
+                    System.out.println(msg);
+                    logger.info(msg);
+                }
+                restored = true;
+            } catch (Exception e) {
+                logger.warn("Unable to restoring snapshot " + snapshotName + " after failed upgrade", e);
+            } finally {
+                try {
+                    if (restoreSnapshot && restored) {
+                        admin.deleteSnapshot(snapshotName);
+                    }
+                } catch (Exception e) {
+                    logger.warn("Unable to delete snapshot " + snapshotName + " after upgrade:", e);
+                } finally {
+                    try {
+                        if (admin != null) {
+                            admin.close();
+                        }
+                    } catch (IOException e) {
+                        logger.warn("Unable to close admin after upgrade:", e);
+                    }
+                }
             }
         }
-        // Mark the table and views as upgraded now
-        for (int i = 0; i < tableNames.size(); i += 3) {
-            String theTenantId = tableNames.get(i);
-            String theSchemaName = tableNames.get(i+1);
-            String theTableName = tableNames.get(i+2);
-            globalConn.createStatement().execute("UPSERT INTO " + PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME + 
-                " (" + PhoenixDatabaseMetaData.TENANT_ID + "," +
-                       PhoenixDatabaseMetaData.TABLE_SCHEM + "," +
-                       PhoenixDatabaseMetaData.TABLE_NAME + "," +
-                       MetaDataEndpointImpl.ROW_KEY_ORDER_OPTIMIZABLE + " BOOLEAN"
-               + ") VALUES (" +
-                       "'" + (theTenantId == null ? StringUtil.EMPTY_STRING : theTenantId) + "'," +
-                       "'" + (theSchemaName == null ? StringUtil.EMPTY_STRING : theSchemaName) + "'," +
-                       "'" + theTableName + "'," +
-                       "TRUE)");
-        }
-        globalConn.commit();
-        for (int i = 0; i < tableNames.size(); i += 3) {
-            String theTenantId = tableNames.get(i);
-            String theSchemaName = tableNames.get(i+1);
-            String theTableName = tableNames.get(i+2);
-            globalConn.getQueryServices().clearTableFromCache(
-                    theTenantId == null ? ByteUtil.EMPTY_BYTE_ARRAY : Bytes.toBytes(theTenantId),
-                    theSchemaName == null ? ByteUtil.EMPTY_BYTE_ARRAY : Bytes.toBytes(schemaName),
-                    Bytes.toBytes(theTableName), HConstants.LATEST_TIMESTAMP);
-        }
-        msg = "Completed upgrade of " + escapedTableName + tenantInfo;
-        System.out.println(msg);
-        logger.info(msg);
     }
     
     private static boolean isInvalidTableToUpgrade(PTable table) throws SQLException {
@@ -1007,16 +1101,10 @@ public class UpgradeUtil {
      * Upgrade tables and their indexes due to a bug causing descending row keys to have a row key that
      * prevents them from being sorted correctly (PHOENIX-2067).
      */
-    public static void upgradeDescVarLengthRowKeys(PhoenixConnection conn, List<String> tablesToUpgrade) throws SQLException {
+    public static void upgradeDescVarLengthRowKeys(PhoenixConnection conn, List<String> tablesToUpgrade, boolean bypassUpgrade) throws SQLException {
         if (tablesToUpgrade.isEmpty()) {
             return;
         }
-        if (conn.getClientInfo(PhoenixRuntime.CURRENT_SCN_ATTRIB) != null) {
-            throw new SQLException("May not specify the CURRENT_SCN property when upgrading");
-        }
-        if (conn.getClientInfo(PhoenixRuntime.TENANT_ID_ATTRIB) != null) {
-            throw new SQLException("May not specify the TENANT_ID_ATTRIB property when upgrading");
-        }
         List<PTable> tablesNeedingUpgrading = Lists.newArrayListWithExpectedSize(tablesToUpgrade.size());
         List<String> invalidTables = Lists.newArrayListWithExpectedSize(tablesToUpgrade.size());
         for (String fullTableName : tablesToUpgrade) {
@@ -1042,23 +1130,23 @@ public class UpgradeUtil {
                 boolean wasUpgraded = false;
                 if (!table.rowKeyOrderOptimizable()) {
                     wasUpgraded = true;
-                    upgradeDescVarLengthRowKeys(upgradeConn, conn, table.getSchemaName().getString(), table.getTableName().getString(), true);
+                    upgradeDescVarLengthRowKeys(upgradeConn, conn, table.getSchemaName().getString(), table.getTableName().getString(), true, bypassUpgrade);
                 }
                 
                 // Upgrade global indexes
                 for (PTable index : table.getIndexes()) {
                     if (!index.rowKeyOrderOptimizable() && index.getIndexType() != IndexType.LOCAL) {
                         wasUpgraded = true;
-                        upgradeDescVarLengthRowKeys(upgradeConn, conn, index.getSchemaName().getString(), index.getTableName().getString(), false);
+                        upgradeDescVarLengthRowKeys(upgradeConn, conn, index.getSchemaName().getString(), index.getTableName().getString(), false, bypassUpgrade);
                     }
                 }
                 
                 String sharedViewIndexName = Bytes.toString(MetaDataUtil.getViewIndexPhysicalName(table.getName().getBytes()));
                 // Upgrade view indexes
-                wasUpgraded |= upgradeSharedIndex(upgradeConn, conn, sharedViewIndexName);
+                wasUpgraded |= upgradeSharedIndex(upgradeConn, conn, sharedViewIndexName, bypassUpgrade);
                 String sharedLocalIndexName = Bytes.toString(MetaDataUtil.getLocalIndexPhysicalName(table.getName().getBytes()));
-                // Upgrade view indexes
-                wasUpgraded |= upgradeSharedIndex(upgradeConn, conn, sharedLocalIndexName);
+                // Upgrade local indexes
+                wasUpgraded |= upgradeSharedIndex(upgradeConn, conn, sharedLocalIndexName, bypassUpgrade);
                 
                 if (!wasUpgraded) {
                     System.out.println("Upgrade not required for this table or its indexes: " + table.getName().getString());
@@ -1074,7 +1162,7 @@ public class UpgradeUtil {
      * physical table.
      * @return true if any upgrades were performed and false otherwise.
      */
-    private static boolean upgradeSharedIndex(PhoenixConnection upgradeConn, PhoenixConnection globalConn, String physicalName) throws SQLException {
+    private static boolean upgradeSharedIndex(PhoenixConnection upgradeConn, PhoenixConnection globalConn, String physicalName, boolean bypassUpgrade) throws SQLException {
         String query =
                 "SELECT TENANT_ID,TABLE_SCHEM,TABLE_NAME\n" + 
                 "FROM SYSTEM.CATALOG cat1\n" + 
@@ -1105,7 +1193,7 @@ public class UpgradeUtil {
             PTable table = PhoenixRuntime.getTable(conn, fullTableName);
             String tableTenantId = table.getTenantId() == null ? null : table.getTenantId().getString();
             if (Objects.equal(lastTenantId, tableTenantId) && !table.rowKeyOrderOptimizable()) {
-                upgradeDescVarLengthRowKeys(upgradeConn, globalConn, table.getSchemaName().getString(), table.getTableName().getString(), false);
+                upgradeDescVarLengthRowKeys(upgradeConn, globalConn, table.getSchemaName().getString(), table.getTableName().getString(), false, bypassUpgrade);
                 wasUpgraded = true;
             }
         }


[20/40] phoenix git commit: PHOENIX-2149 MAX Value of Sequences not honored when closing Connection between calls to NEXT VALUE FOR (Jan Fernando)

Posted by ma...@apache.org.
PHOENIX-2149 MAX Value of Sequences not honored when closing Connection between calls to NEXT VALUE FOR (Jan Fernando)


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/28a8e977
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/28a8e977
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/28a8e977

Branch: refs/heads/calcite
Commit: 28a8e9774bbea0d44bc716d8a495a6b93768bbef
Parents: c0d0c79
Author: Thomas D'Silva <td...@salesforce.com>
Authored: Mon Jul 27 13:15:17 2015 -0700
Committer: Thomas D'Silva <td...@salesforce.com>
Committed: Mon Jul 27 13:15:17 2015 -0700

----------------------------------------------------------------------
 .../org/apache/phoenix/end2end/SequenceIT.java  | 33 ++++++++++++++++++++
 .../org/apache/phoenix/schema/Sequence.java     |  3 +-
 2 files changed, 34 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/28a8e977/phoenix-core/src/it/java/org/apache/phoenix/end2end/SequenceIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SequenceIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SequenceIT.java
index 4273022..78f8132 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SequenceIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SequenceIT.java
@@ -54,6 +54,7 @@ import com.google.common.collect.Lists;
 
 public class SequenceIT extends BaseClientManagedTimeIT {
     private static final String NEXT_VAL_SQL = "SELECT NEXT VALUE FOR foo.bar FROM SYSTEM.\"SEQUENCE\"";
+    private static final String SELECT_NEXT_VALUE_SQL = "SELECT NEXT VALUE FOR %s FROM SYSTEM.\"SEQUENCE\"";
     private static final long BATCH_SIZE = 3;
    
     private Connection conn;
@@ -1147,6 +1148,38 @@ public class SequenceIT extends BaseClientManagedTimeIT {
         assertEquals(1, rs.getLong("metric_val"));
         assertFalse(rs.next());
     }
+    
+    @Test
+    /**
+     * Test to validate that the bug discovered in PHOENIX-2149 has been fixed. There was an issue
+     * whereby, when closing connections and returning sequences we were not setting the limit
+     * reached flag correctly and this was causing the max value to be ignored as the LIMIT_REACHED_FLAG
+     * value was being unset from true to false.
+     */
+    public void testNextValuesForSequenceClosingConnections() throws Exception {
+
+        // Create Sequence
+        nextConnection();
+        conn.createStatement().execute("CREATE SEQUENCE seqtest.closeconn START WITH 4990 MINVALUE 4990 MAXVALUE 5000 CACHE 10");
+        nextConnection();
+        
+        // Call NEXT VALUE FOR 1 time more than available values in the Sequence. We expected the final time
+        // to throw an error as we will have reached the max value
+        try {
+            long val = 0L;
+            for (int i = 0; i <= 11; i++) {
+                ResultSet rs = conn.createStatement().executeQuery(String.format(SELECT_NEXT_VALUE_SQL, "seqtest.closeconn"));
+                rs.next();
+                val = rs.getLong(1);
+                nextConnection();
+            }
+            fail("Expect to fail as we have arrived at the max sequence value " + val);
+        } catch (SQLException e) {
+            assertEquals(SQLExceptionCode.SEQUENCE_VAL_REACHED_MAX_VALUE.getErrorCode(),
+                e.getErrorCode());
+            assertTrue(e.getNextException() == null);
+        }
+    }
 
     private void insertEvent(long id, String userId, long val) throws SQLException {
         PreparedStatement stmt = conn.prepareStatement("UPSERT INTO events VALUES(?,?,?)");

http://git-wip-us.apache.org/repos/asf/phoenix/blob/28a8e977/phoenix-core/src/main/java/org/apache/phoenix/schema/Sequence.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/Sequence.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/Sequence.java
index adca5e8..a2041f7 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/Sequence.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/Sequence.java
@@ -302,8 +302,7 @@ public class Sequence {
         Map<byte[], List<Cell>> familyMap = append.getFamilyCellMap();
         familyMap.put(PhoenixDatabaseMetaData.SEQUENCE_FAMILY_BYTES, Arrays.<Cell>asList(
         		(Cell)KeyValueUtil.newKeyValue(key, PhoenixDatabaseMetaData.SEQUENCE_FAMILY_BYTES, PhoenixDatabaseMetaData.CURRENT_VALUE_BYTES, value.timestamp, PLong.INSTANCE.toBytes(value.currentValue)),
-        		// set LIMIT_REACHED flag to false since we are returning unused sequence values
-        		(Cell)KeyValueUtil.newKeyValue(key, PhoenixDatabaseMetaData.SEQUENCE_FAMILY_BYTES, PhoenixDatabaseMetaData.LIMIT_REACHED_FLAG_BYTES, value.timestamp, PDataType.FALSE_BYTES)
+        		(Cell)KeyValueUtil.newKeyValue(key, PhoenixDatabaseMetaData.SEQUENCE_FAMILY_BYTES, PhoenixDatabaseMetaData.LIMIT_REACHED_FLAG_BYTES, value.timestamp, PBoolean.INSTANCE.toBytes(value.limitReached))
                 ));
         return append;
     }


[28/40] phoenix git commit: PHOENIX-1994 - TestIndexWriter#testFailureOnRunningUpdateAbortsPending() deadlocks on JDK 8

Posted by ma...@apache.org.
PHOENIX-1994 - TestIndexWriter#testFailureOnRunningUpdateAbortsPending() deadlocks on JDK 8


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/d401fa3a
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/d401fa3a
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/d401fa3a

Branch: refs/heads/calcite
Commit: d401fa3a6f5ec9787b120643881a389b9af7b19f
Parents: c811cf6
Author: Cody Marcel <co...@gmail.com>
Authored: Mon Aug 10 12:08:07 2015 -0700
Committer: Cody Marcel <co...@gmail.com>
Committed: Mon Aug 10 12:08:07 2015 -0700

----------------------------------------------------------------------
 .../java/org/apache/phoenix/hbase/index/write/TestIndexWriter.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/d401fa3a/phoenix-core/src/test/java/org/apache/phoenix/hbase/index/write/TestIndexWriter.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/hbase/index/write/TestIndexWriter.java b/phoenix-core/src/test/java/org/apache/phoenix/hbase/index/write/TestIndexWriter.java
index 37a8cf4..8f576cf 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/hbase/index/write/TestIndexWriter.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/hbase/index/write/TestIndexWriter.java
@@ -145,7 +145,7 @@ public class TestIndexWriter {
     Abortable abort = new StubAbortable();
     Stoppable stop = Mockito.mock(Stoppable.class);
     // single thread factory so the older request gets queued
-    ExecutorService exec = Executors.newFixedThreadPool(1);
+    ExecutorService exec = Executors.newFixedThreadPool(3);
     Map<ImmutableBytesPtr, HTableInterface> tables = new HashMap<ImmutableBytesPtr, HTableInterface>();
     FakeTableFactory factory = new FakeTableFactory(tables);
 


[25/40] phoenix git commit: PHOENIX-2140 Implement get_byte/set_byte/get_bit/set_bit Binary String build-in function (Shuxiong Ye)

Posted by ma...@apache.org.
PHOENIX-2140 Implement get_byte/set_byte/get_bit/set_bit Binary String build-in function (Shuxiong Ye)


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/caf65ca7
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/caf65ca7
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/caf65ca7

Branch: refs/heads/calcite
Commit: caf65ca765040709aeb1ea5da1281f1eecae2614
Parents: d41a0fc
Author: Samarth <sa...@salesforce.com>
Authored: Wed Aug 5 09:42:15 2015 -0700
Committer: Samarth <sa...@salesforce.com>
Committed: Wed Aug 5 09:42:15 2015 -0700

----------------------------------------------------------------------
 .../end2end/GetSetByteBitFunctionEnd2EndIT.java | 100 ++++++++++
 .../phoenix/expression/ExpressionType.java      |  10 +-
 .../expression/function/GetBitFunction.java     |  96 ++++++++++
 .../expression/function/GetByteFunction.java    |  96 ++++++++++
 .../expression/function/SetBitFunction.java     |  81 ++++++++
 .../expression/function/SetByteFunction.java    |  81 ++++++++
 .../apache/phoenix/schema/types/PBinary.java    |   2 +-
 .../phoenix/schema/types/PBinaryBase.java       |  86 +++++++++
 .../apache/phoenix/schema/types/PVarbinary.java |   2 +-
 .../phoenix/compile/WhereOptimizerTest.java     |  33 +++-
 .../expression/GetSetByteBitFunctionTest.java   | 189 +++++++++++++++++++
 .../java/org/apache/phoenix/query/BaseTest.java |   8 +
 .../java/org/apache/phoenix/util/TestUtil.java  |   1 +
 13 files changed, 780 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/caf65ca7/phoenix-core/src/it/java/org/apache/phoenix/end2end/GetSetByteBitFunctionEnd2EndIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/GetSetByteBitFunctionEnd2EndIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/GetSetByteBitFunctionEnd2EndIT.java
new file mode 100644
index 0000000..a7f7ca3
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/GetSetByteBitFunctionEnd2EndIT.java
@@ -0,0 +1,100 @@
+/*
+ * 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.phoenix.end2end;
+
+import static org.apache.phoenix.util.TestUtil.closeStmtAndConn;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+
+import org.apache.phoenix.expression.function.GetBitFunction;
+import org.apache.phoenix.expression.function.GetByteFunction;
+import org.apache.phoenix.expression.function.SetBitFunction;
+import org.apache.phoenix.expression.function.SetByteFunction;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * End to end tests for {@link GetByteFunction} {@link SetByteFunction} {@link GetBitFunction}
+ * {@link SetBitFunction}
+ */
+public class GetSetByteBitFunctionEnd2EndIT extends BaseHBaseManagedTimeIT {
+
+    private static final String KEY = "key";
+
+    @Before
+    public void initTable() throws Exception {
+        Connection conn = null;
+        PreparedStatement stmt = null;
+        try {
+            conn = DriverManager.getConnection(getUrl());
+            String ddl;
+            ddl = "CREATE TABLE ta (k VARCHAR NOT NULL PRIMARY KEY, b BINARY(4), vb VARBINARY)";
+            conn.createStatement().execute(ddl);
+            conn.commit();
+        } finally {
+            closeStmtAndConn(stmt, conn);
+        }
+    }
+
+    @Test
+    public void test() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO ta VALUES (?, ?, ?)");
+        stmt.setString(1, KEY);
+        stmt.setBytes(2, new byte[] { 1, 2, 3, 4 });
+        stmt.setBytes(3, new byte[] { 1, 2, 3, 4 });
+        stmt.executeUpdate();
+        conn.commit();
+        ResultSet rs =
+                conn.createStatement()
+                        .executeQuery(
+                            "SELECT GET_BYTE(vb, 1), GET_BYTE(b, 1) FROM ta WHERE GET_BYTE(vb, 1)=2 and GET_BYTE(b, 1)=2");
+        assertTrue(rs.next());
+        assertEquals(2, rs.getInt(1));
+        assertEquals(2, rs.getInt(2));
+        assertTrue(!rs.next());
+        rs =
+                conn.createStatement()
+                        .executeQuery(
+                            "SELECT GET_BIT(b, 0),GET_BIT(b, 9) FROM ta WHERE GET_BIT(vb, 0)=1 and GET_BIT(vb, 9)=1");
+        assertTrue(rs.next());
+        assertEquals(1, rs.getInt(1));
+        assertEquals(1, rs.getInt(2));
+        assertTrue(!rs.next());
+        rs =
+                conn.createStatement().executeQuery(
+                    "SELECT SET_BYTE(vb, 1, 1), SET_BYTE(b, 1, 1) FROM ta");
+        assertTrue(rs.next());
+        assertArrayEquals(new byte[] { 1, 1, 3, 4 }, rs.getBytes(1));
+        assertArrayEquals(new byte[] { 1, 1, 3, 4 }, rs.getBytes(2));
+        assertTrue(!rs.next());
+        rs =
+                conn.createStatement().executeQuery(
+                    "SELECT SET_BIT(vb, 8, 1), SET_BIT(b, 8, 1) FROM ta");
+        assertTrue(rs.next());
+        assertArrayEquals(new byte[] { 1, 3, 3, 4 }, rs.getBytes(1));
+        assertArrayEquals(new byte[] { 1, 3, 3, 4 }, rs.getBytes(2));
+        assertTrue(!rs.next());
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/caf65ca7/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
index 9e9cb45..5dbab69 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
@@ -52,6 +52,8 @@ import org.apache.phoenix.expression.function.FirstValueFunction;
 import org.apache.phoenix.expression.function.FloorDateExpression;
 import org.apache.phoenix.expression.function.FloorDecimalExpression;
 import org.apache.phoenix.expression.function.FloorFunction;
+import org.apache.phoenix.expression.function.GetBitFunction;
+import org.apache.phoenix.expression.function.GetByteFunction;
 import org.apache.phoenix.expression.function.HourFunction;
 import org.apache.phoenix.expression.function.IndexStateNameFunction;
 import org.apache.phoenix.expression.function.InstrFunction;
@@ -88,6 +90,8 @@ import org.apache.phoenix.expression.function.SQLIndexTypeFunction;
 import org.apache.phoenix.expression.function.SQLTableTypeFunction;
 import org.apache.phoenix.expression.function.SQLViewTypeFunction;
 import org.apache.phoenix.expression.function.SecondFunction;
+import org.apache.phoenix.expression.function.SetBitFunction;
+import org.apache.phoenix.expression.function.SetByteFunction;
 import org.apache.phoenix.expression.function.SignFunction;
 import org.apache.phoenix.expression.function.SqlTypeNameFunction;
 import org.apache.phoenix.expression.function.SqrtFunction;
@@ -253,7 +257,11 @@ public enum ExpressionType {
     ArrayConcatFunction(ArrayConcatFunction.class),
     ArrayFillFunction(ArrayFillFunction.class),
     ArrayToStringFunction(ArrayToStringFunction.class),
-    StringToArrayFunction(StringToArrayFunction.class)
+    StringToArrayFunction(StringToArrayFunction.class),
+    GetByteFunction(GetByteFunction.class),
+    SetByteFunction(SetByteFunction.class),
+    GetBitFunction(GetBitFunction.class),
+    SetBitFunction(SetBitFunction.class)
     ;
 
     ExpressionType(Class<? extends Expression> clazz) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/caf65ca7/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetBitFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetBitFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetBitFunction.java
new file mode 100644
index 0000000..f26a53d
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetBitFunction.java
@@ -0,0 +1,96 @@
+/*
+ * 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.phoenix.expression.function;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.Determinism;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.PBinary;
+import org.apache.phoenix.schema.types.PBinaryBase;
+import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PInteger;
+import org.apache.phoenix.schema.types.PVarbinary;
+
+@BuiltInFunction(name = GetBitFunction.NAME, args = {
+        @Argument(allowedTypes = { PBinary.class, PVarbinary.class }),
+        @Argument(allowedTypes = { PInteger.class }) })
+public class GetBitFunction extends PrefixFunction {
+
+    public static final String NAME = “GET_BIT”;
+
+    private Integer offsetPreCompute;
+
+    public GetBitFunction() {
+    }
+
+    public GetBitFunction(List<Expression> children) throws SQLException {
+        super(children);
+        init();
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        // get offset parameter
+        int offset;
+        if (offsetPreCompute == null) {
+            Expression offsetExpr = children.get(1);
+            if (!offsetExpr.evaluate(tuple, ptr)) return false;
+            offset = (Integer) PInteger.INSTANCE.toObject(ptr, offsetExpr.getSortOrder());
+        } else offset = offsetPreCompute;
+        // get binary data parameter
+        Expression dataExpr = children.get(0);
+        if (!dataExpr.evaluate(tuple, ptr)) return false;
+        if (ptr.getLength() == 0) return true;
+        int len = ptr.getLength() * Byte.SIZE;
+        offset = (offset % len + len) % len;
+        // set result
+        ((PBinaryBase) dataExpr.getDataType()).getBit(ptr, dataExpr.getSortOrder(), offset, ptr);
+        return true;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PInteger.INSTANCE;
+    }
+
+    private void init() {
+        Expression offsetExpr = children.get(1);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        if (offsetExpr.isStateless() && offsetExpr.getDeterminism() == Determinism.ALWAYS
+                && offsetExpr.evaluate(null, ptr)) {
+            offsetPreCompute = (Integer) PInteger.INSTANCE.toObject(ptr, offsetExpr.getSortOrder());
+        } else offsetPreCompute = null;
+    }
+
+    @Override
+    public OrderPreserving preservesOrder() {
+        return (offsetPreCompute != null && offsetPreCompute == 0) ? OrderPreserving.YES_IF_LAST
+                : OrderPreserving.NO;
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/caf65ca7/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetByteFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetByteFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetByteFunction.java
new file mode 100644
index 0000000..8e455ae
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetByteFunction.java
@@ -0,0 +1,96 @@
+/*
+ * 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.phoenix.expression.function;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.Determinism;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.PBinary;
+import org.apache.phoenix.schema.types.PBinaryBase;
+import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PInteger;
+import org.apache.phoenix.schema.types.PVarbinary;
+
+@BuiltInFunction(name = GetByteFunction.NAME, args = {
+        @Argument(allowedTypes = { PBinary.class, PVarbinary.class }),
+        @Argument(allowedTypes = { PInteger.class }) })
+public class GetByteFunction extends PrefixFunction {
+
+    public static final String NAME = "GET_BYTE";
+
+    private Integer offsetPreCompute;
+
+    public GetByteFunction() {
+    }
+
+    public GetByteFunction(List<Expression> children) throws SQLException {
+        super(children);
+        init();
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        // get offset parameter
+        int offset;
+        if (offsetPreCompute == null) {
+            Expression offsetExpr = children.get(1);
+            if (!offsetExpr.evaluate(tuple, ptr)) return false;
+            offset = (Integer) PInteger.INSTANCE.toObject(ptr, offsetExpr.getSortOrder());
+        } else offset = offsetPreCompute;
+        // get binary data parameter
+        Expression dataExpr = children.get(0);
+        if (!dataExpr.evaluate(tuple, ptr)) return false;
+        if (ptr.getLength() == 0) return true;
+        int len = ptr.getLength();
+        offset = (offset % len + len) % len;
+        // set result
+        ((PBinaryBase) dataExpr.getDataType()).getByte(ptr, dataExpr.getSortOrder(), offset, ptr);
+        return true;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PInteger.INSTANCE;
+    }
+
+    private void init() {
+        Expression offsetExpr = children.get(1);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        if (offsetExpr.isStateless() && offsetExpr.getDeterminism() == Determinism.ALWAYS
+                && offsetExpr.evaluate(null, ptr)) {
+            offsetPreCompute = (Integer) PInteger.INSTANCE.toObject(ptr, offsetExpr.getSortOrder());
+        } else offsetPreCompute = null;
+    }
+
+    @Override
+    public OrderPreserving preservesOrder() {
+        return (offsetPreCompute != null && offsetPreCompute == 0) ? OrderPreserving.YES_IF_LAST
+                : OrderPreserving.NO;
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/caf65ca7/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetBitFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetBitFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetBitFunction.java
new file mode 100644
index 0000000..3c85c9c
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetBitFunction.java
@@ -0,0 +1,81 @@
+/*
+ * 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.phoenix.expression.function;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.PBinary;
+import org.apache.phoenix.schema.types.PBinaryBase;
+import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PInteger;
+import org.apache.phoenix.schema.types.PVarbinary;
+
+@BuiltInFunction(name = SetBitFunction.NAME,
+        args = { @Argument(allowedTypes = { PBinary.class, PVarbinary.class }),
+                @Argument(allowedTypes = { PInteger.class }),
+                @Argument(allowedTypes = { PInteger.class }) })
+public class SetBitFunction extends ScalarFunction {
+
+    public static final String NAME = “SET_BIT”;
+
+    public SetBitFunction() {
+    }
+
+    public SetBitFunction(List<Expression> children) throws SQLException {
+        super(children);
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        // get offset parameter
+        Expression offsetExpr = children.get(1);
+        if (!offsetExpr.evaluate(tuple, ptr)) return false;
+        int offset = (Integer) PInteger.INSTANCE.toObject(ptr, offsetExpr.getSortOrder());
+        // get newValue parameter
+        Expression newValueExpr = children.get(2);
+        if (!newValueExpr.evaluate(tuple, ptr)) return false;
+        int newValue = (Integer) PInteger.INSTANCE.toObject(ptr, newValueExpr.getSortOrder());
+        byte newByteValue = (byte) (newValue & 0x1);
+        // get binary data parameter
+        Expression dataExpr = children.get(0);
+        if (!dataExpr.evaluate(tuple, ptr)) return false;
+        if (ptr.getLength() == 0) return true;
+        int len = ptr.getLength() * Byte.SIZE;
+        offset = (offset % len + len) % len;
+        // set result
+        ((PBinaryBase) dataExpr.getDataType()).setBit(ptr, dataExpr.getSortOrder(), offset,
+            newByteValue, ptr);
+        return true;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return children.get(0).getDataType();
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/caf65ca7/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetByteFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetByteFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetByteFunction.java
new file mode 100644
index 0000000..b32bbcf
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetByteFunction.java
@@ -0,0 +1,81 @@
+/*
+ * 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.phoenix.expression.function;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.PBinary;
+import org.apache.phoenix.schema.types.PBinaryBase;
+import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PInteger;
+import org.apache.phoenix.schema.types.PVarbinary;
+
+@BuiltInFunction(name = SetByteFunction.NAME,
+        args = { @Argument(allowedTypes = { PBinary.class, PVarbinary.class }),
+                @Argument(allowedTypes = { PInteger.class }),
+                @Argument(allowedTypes = { PInteger.class }) })
+public class SetByteFunction extends ScalarFunction {
+
+    public static final String NAME = “SET_BYTE”;
+
+    public SetByteFunction() {
+    }
+
+    public SetByteFunction(List<Expression> children) throws SQLException {
+        super(children);
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        // get offset parameter
+        Expression offsetExpr = children.get(1);
+        if (!offsetExpr.evaluate(tuple, ptr)) return false;
+        int offset = (Integer) PInteger.INSTANCE.toObject(ptr, offsetExpr.getSortOrder());
+        // get newValue parameter
+        Expression newValueExpr = children.get(2);
+        if (!newValueExpr.evaluate(tuple, ptr)) return false;
+        int newValue = (Integer) PInteger.INSTANCE.toObject(ptr, newValueExpr.getSortOrder());
+        byte newByteValue = (byte) (newValue & 0xff);
+        // get binary data parameter
+        Expression dataExpr = children.get(0);
+        if (!dataExpr.evaluate(tuple, ptr)) return false;
+        if (ptr.getLength() == 0) return true;
+        int len = ptr.getLength();
+        offset = (offset % len + len) % len;
+        // set result
+        ((PBinaryBase) dataExpr.getDataType()).setByte(ptr, dataExpr.getSortOrder(), offset,
+            newByteValue, ptr);
+        return true;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return children.get(0).getDataType();
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/caf65ca7/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinary.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinary.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinary.java
index 8e0c4b5..9aa3f42 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinary.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinary.java
@@ -28,7 +28,7 @@ import org.apache.phoenix.exception.DataExceedsCapacityException;
 import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.schema.SortOrder;
 
-public class PBinary extends PDataType<byte[]> {
+public class PBinary extends PBinaryBase {
 
   public static final PBinary INSTANCE = new PBinary();
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/caf65ca7/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryBase.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryBase.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryBase.java
new file mode 100644
index 0000000..ec0793e
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryBase.java
@@ -0,0 +1,86 @@
+/*
+ * 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.phoenix.schema.types;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.schema.SortOrder;
+
+public abstract class PBinaryBase extends PDataType<byte[]> {
+
+    protected PBinaryBase(String sqlTypeName, int sqlType, Class clazz,
+            org.apache.phoenix.schema.types.PDataType.PDataCodec codec, int ordinal) {
+        super(sqlTypeName, sqlType, clazz, codec, ordinal);
+    }
+
+    public void getByte(ImmutableBytesWritable ptr, SortOrder sortOrder, int offset,
+            ImmutableBytesWritable outPtr) {
+        getByte(ptr.get(), ptr.getOffset(), ptr.getLength(), sortOrder, offset, outPtr);
+    }
+
+    public void getByte(byte[] bytes, int offset, int length, SortOrder sortOrder, int off,
+            ImmutableBytesWritable outPtr) {
+        byte ret = bytes[offset + off];
+        if (sortOrder == SortOrder.DESC) ret = SortOrder.invert(ret);
+        outPtr.set(PInteger.INSTANCE.toBytes(Integer.valueOf(ret)));
+    }
+
+    public void setByte(ImmutableBytesWritable ptr, SortOrder sortOrder, int offset, byte newValue,
+            ImmutableBytesWritable outPtr) {
+        setByte(ptr.get(), ptr.getOffset(), ptr.getLength(), sortOrder, offset, newValue, outPtr);
+    }
+
+    public void setByte(byte[] bytes, int offset, int length, SortOrder sortOrder, int off,
+            byte newValue, ImmutableBytesWritable outPtr) {
+        byte[] ret;
+        if (sortOrder == SortOrder.ASC) {
+            ret = new byte[length];
+            System.arraycopy(bytes, offset, ret, 0, length);
+        } else {
+            ret = SortOrder.invert(bytes, offset, length);
+        }
+        ret[off] = newValue;
+        outPtr.set(ret);
+    }
+
+    public void getBit(ImmutableBytesWritable ptr, SortOrder sortOrder, int offset,
+            ImmutableBytesWritable outPtr) {
+        getBit(ptr.get(), ptr.getOffset(), ptr.getLength(), sortOrder, offset, outPtr);
+    }
+
+    public void getBit(byte[] bytes, int offset, int length, SortOrder sortOrder, int off,
+            ImmutableBytesWritable outPtr) {
+        byte ret = bytes[offset + (off / Byte.SIZE)];
+        if (sortOrder == SortOrder.DESC) ret = SortOrder.invert(ret);
+        ret &= 1 << (off % Byte.SIZE);
+        ret = (ret != 0) ? (byte) 1 : (byte) 0;
+        outPtr.set(PInteger.INSTANCE.toBytes(Integer.valueOf(ret)));
+    }
+
+    public void setBit(ImmutableBytesWritable ptr, SortOrder sortOrder, int offset, byte newValue,
+            ImmutableBytesWritable outPtr) {
+        setBit(ptr.get(), ptr.getOffset(), ptr.getLength(), sortOrder, offset, newValue, outPtr);
+    }
+
+    public void setBit(byte[] bytes, int offset, int length, SortOrder sortOrder, int off,
+            byte newValue, ImmutableBytesWritable outPtr) {
+        byte ret = bytes[offset + (off / Byte.SIZE)];
+        if (sortOrder == SortOrder.DESC) ret = SortOrder.invert(ret);
+        ret = (byte) ((ret & (~(1 << (off % Byte.SIZE)))) | (newValue << (off % Byte.SIZE)));
+        setByte(bytes, offset, length, sortOrder, off / Byte.SIZE, ret, outPtr);
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/caf65ca7/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PVarbinary.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PVarbinary.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PVarbinary.java
index bb1d4c6..aafa1c6 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PVarbinary.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PVarbinary.java
@@ -26,7 +26,7 @@ import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.util.ByteUtil;
 
-public class PVarbinary extends PDataType<byte[]> {
+public class PVarbinary extends PBinaryBase {
 
   public static final PVarbinary INSTANCE = new PVarbinary();
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/caf65ca7/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java
index c1787ca..227cbd7 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereOptimizerTest.java
@@ -17,6 +17,7 @@
  */
 package org.apache.phoenix.compile;
 
+import static org.apache.phoenix.util.TestUtil.BINARY_NAME;
 import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
 import static org.apache.phoenix.util.TestUtil.assertDegenerate;
 import static org.apache.phoenix.util.TestUtil.assertEmptyScanKey;
@@ -68,8 +69,6 @@ import org.apache.phoenix.util.StringUtil;
 import org.apache.phoenix.util.TestUtil;
 import org.junit.Test;
 
-
-
 public class WhereOptimizerTest extends BaseConnectionlessQueryTest {
     
     private static StatementContext compileStatement(String query) throws SQLException {
@@ -106,6 +105,36 @@ public class WhereOptimizerTest extends BaseConnectionlessQueryTest {
     }
 
     @Test
+    public void testGetByteBitExpression() throws SQLException {
+        ensureTableCreated(getUrl(), TestUtil.BINARY_NAME);
+        int result = 1;
+        String query = "select * from " + BINARY_NAME + " where GET_BYTE(a_binary, 0)=" + result;
+        Scan scan = compileStatement(query).getScan();
+
+        byte[] tmpBytes, tmpBytes2, tmpBytes3;
+        tmpBytes = PInteger.INSTANCE.toBytes(result);
+        tmpBytes2 = new byte[16];
+        System.arraycopy(tmpBytes, 0, tmpBytes2, 0, tmpBytes.length);
+        tmpBytes = ByteUtil.nextKey(tmpBytes);
+        tmpBytes3 = new byte[16];
+        System.arraycopy(tmpBytes, 0, tmpBytes3, 0, tmpBytes.length);
+        assertArrayEquals(tmpBytes2, scan.getStartRow());
+        assertArrayEquals(tmpBytes3, scan.getStopRow());
+
+        query = "select * from " + BINARY_NAME + " where GET_BIT(a_binary, 0)=" + result;
+        scan = compileStatement(query).getScan();
+
+        tmpBytes = PInteger.INSTANCE.toBytes(result);
+        tmpBytes2 = new byte[16];
+        System.arraycopy(tmpBytes, 0, tmpBytes2, 0, tmpBytes.length);
+        tmpBytes = ByteUtil.nextKey(tmpBytes);
+        tmpBytes3 = new byte[16];
+        System.arraycopy(tmpBytes, 0, tmpBytes3, 0, tmpBytes.length);
+        assertArrayEquals(tmpBytes2, scan.getStartRow());
+        assertArrayEquals(tmpBytes3, scan.getStopRow());
+    }
+
+    @Test
     public void testSingleCharPaddedKeyExpression() throws SQLException {
         String tenantId = "1";
         String query = "select * from atable where organization_id='" + tenantId + "'";

http://git-wip-us.apache.org/repos/asf/phoenix/blob/caf65ca7/phoenix-core/src/test/java/org/apache/phoenix/expression/GetSetByteBitFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/GetSetByteBitFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/GetSetByteBitFunctionTest.java
new file mode 100644
index 0000000..f01ce3b
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/GetSetByteBitFunctionTest.java
@@ -0,0 +1,189 @@
+/*
+ * 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.phoenix.expression;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.function.GetBitFunction;
+import org.apache.phoenix.expression.function.GetByteFunction;
+import org.apache.phoenix.expression.function.SetBitFunction;
+import org.apache.phoenix.expression.function.SetByteFunction;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.types.PBinary;
+import org.apache.phoenix.schema.types.PBinaryBase;
+import org.apache.phoenix.schema.types.PInteger;
+import org.apache.phoenix.schema.types.PVarbinary;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Unit tests for {@link GetByteFunction} {@link SetByteFunction} {@link GetBitFunction}
+ * {@link SetBitFunction}
+ */
+public class GetSetByteBitFunctionTest {
+    private void testGetByteExpression(Expression data, Expression offset, int expected)
+            throws SQLException {
+        List<Expression> expressions = Lists.newArrayList(data, offset);
+        Expression getByteFunction = new GetByteFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        getByteFunction.evaluate(null, ptr);
+        Integer result =
+                (Integer) getByteFunction.getDataType().toObject(ptr,
+                    getByteFunction.getSortOrder());
+        assertEquals(expected, result.intValue());
+    }
+
+    private void testSetByteExpression(Expression data, Expression offset, Expression newValue,
+            byte[] expected) throws SQLException {
+        List<Expression> expressions = Lists.newArrayList(data, offset, newValue);
+        Expression setByteFunction = new SetByteFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        setByteFunction.evaluate(null, ptr);
+        byte[] result =
+                (byte[]) setByteFunction.getDataType()
+                        .toObject(ptr, setByteFunction.getSortOrder());
+        assertArrayEquals(expected, result);
+    }
+
+    private void testGetByte(byte[] bytes, int offset, PBinaryBase dataType, int expected)
+            throws SQLException {
+        LiteralExpression dataExpr, offsetExpr;
+        dataExpr = LiteralExpression.newConstant(bytes, dataType, SortOrder.ASC);
+        offsetExpr = LiteralExpression.newConstant(offset, PInteger.INSTANCE, SortOrder.ASC);
+        testGetByteExpression(dataExpr, offsetExpr, expected);
+        dataExpr = LiteralExpression.newConstant(bytes, dataType, SortOrder.DESC);
+        offsetExpr = LiteralExpression.newConstant(offset, PInteger.INSTANCE, SortOrder.DESC);
+        testGetByteExpression(dataExpr, offsetExpr, expected);
+    }
+
+    private void testSetByte(byte[] bytes, int offset, int newValue, PBinaryBase dataType,
+            byte[] expected) throws SQLException {
+        LiteralExpression dataExpr, offsetExpr, newValueExpr;
+        dataExpr = LiteralExpression.newConstant(bytes, dataType, SortOrder.ASC);
+        offsetExpr = LiteralExpression.newConstant(offset, PInteger.INSTANCE, SortOrder.ASC);
+        newValueExpr = LiteralExpression.newConstant(newValue, PInteger.INSTANCE, SortOrder.ASC);
+        testSetByteExpression(dataExpr, offsetExpr, newValueExpr, expected);
+        dataExpr = LiteralExpression.newConstant(bytes, dataType, SortOrder.DESC);
+        offsetExpr = LiteralExpression.newConstant(offset, PInteger.INSTANCE, SortOrder.DESC);
+        newValueExpr = LiteralExpression.newConstant(newValue, PInteger.INSTANCE, SortOrder.DESC);
+        testSetByteExpression(dataExpr, offsetExpr, newValueExpr, expected);
+    }
+
+    @Test
+    public void testByteBatch() throws SQLException {
+        byte[] bytes = new byte[256];
+        int sum = 0;
+        for (int i = 0; i < 256; ++i) {
+            bytes[i] = (byte) (i & 0xff);
+            sum += bytes[i];
+        }
+        assertEquals(-128, sum);
+        for (int offset = 0; offset < 256; ++offset) {
+            testGetByte(bytes, offset, PBinary.INSTANCE, bytes[offset]);
+            testGetByte(bytes, offset, PVarbinary.INSTANCE, bytes[offset]);
+        }
+        for (int offset = 0; offset < 256; ++offset)
+            for (int tmp = Byte.MIN_VALUE; tmp <= Byte.MAX_VALUE; ++tmp) {
+                byte[] expected = new byte[bytes.length];
+                System.arraycopy(bytes, 0, expected, 0, bytes.length);
+                expected[offset] = (byte) (tmp & 0xff);
+                testSetByte(bytes, offset, tmp, PBinary.INSTANCE, expected);
+            }
+    }
+
+    private void testGetBitExpression(Expression data, Expression offset, int expected)
+            throws SQLException {
+        List<Expression> expressions = Lists.newArrayList(data, offset);
+        Expression getBitFunction = new GetBitFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        getBitFunction.evaluate(null, ptr);
+        Integer result =
+                (Integer) getBitFunction.getDataType().toObject(ptr, getBitFunction.getSortOrder());
+        assertEquals(expected, result.intValue());
+    }
+
+    private void testSetBitExpression(Expression data, Expression offset, Expression newValue,
+            byte[] expected) throws SQLException {
+        List<Expression> expressions = Lists.newArrayList(data, offset, newValue);
+        Expression setBitFunction = new SetBitFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        setBitFunction.evaluate(null, ptr);
+        byte[] result =
+                (byte[]) setBitFunction.getDataType().toObject(ptr, setBitFunction.getSortOrder());
+        assertArrayEquals(expected, result);
+    }
+
+    private void testGetBit(byte[] bytes, int offset, PBinaryBase dataType, int expected)
+            throws SQLException {
+        LiteralExpression dataExpr, offsetExpr;
+        dataExpr = LiteralExpression.newConstant(bytes, dataType, SortOrder.ASC);
+        offsetExpr = LiteralExpression.newConstant(offset, PInteger.INSTANCE, SortOrder.ASC);
+        testGetBitExpression(dataExpr, offsetExpr, expected);
+        dataExpr = LiteralExpression.newConstant(bytes, dataType, SortOrder.DESC);
+        offsetExpr = LiteralExpression.newConstant(offset, PInteger.INSTANCE, SortOrder.DESC);
+        testGetBitExpression(dataExpr, offsetExpr, expected);
+    }
+
+    private void testSetBit(byte[] bytes, int offset, int newValue, PBinaryBase dataType,
+            byte[] expected) throws SQLException {
+        LiteralExpression dataExpr, offsetExpr, newValueExpr;
+        dataExpr = LiteralExpression.newConstant(bytes, dataType, SortOrder.ASC);
+        offsetExpr = LiteralExpression.newConstant(offset, PInteger.INSTANCE, SortOrder.ASC);
+        newValueExpr = LiteralExpression.newConstant(newValue, PInteger.INSTANCE, SortOrder.ASC);
+        testSetBitExpression(dataExpr, offsetExpr, newValueExpr, expected);
+        dataExpr = LiteralExpression.newConstant(bytes, dataType, SortOrder.DESC);
+        offsetExpr = LiteralExpression.newConstant(offset, PInteger.INSTANCE, SortOrder.DESC);
+        newValueExpr = LiteralExpression.newConstant(newValue, PInteger.INSTANCE, SortOrder.DESC);
+        testSetBitExpression(dataExpr, offsetExpr, newValueExpr, expected);
+    }
+
+    @Test
+    public void testGetBitBatch() throws SQLException {
+        byte[] bytes = new byte[256];
+        int sum = 0;
+        for (int i = 0; i < 256; ++i) {
+            bytes[i] = (byte) (i & 0xff);
+            sum += bytes[i];
+        }
+        assertEquals(-128, sum);
+        for (int offset = 0; offset < 256 * Byte.SIZE; ++offset) {
+            byte expected =
+                    (bytes[offset / Byte.SIZE] & (1 << (offset % Byte.SIZE))) != 0 ? (byte) 1
+                            : (byte) 0;
+            testGetBit(bytes, offset, PBinary.INSTANCE, expected);
+            testGetBit(bytes, offset, PVarbinary.INSTANCE, expected);
+        }
+        for (int offset = 0; offset < 256 * Byte.SIZE; ++offset)
+            for (int tmp = 0; tmp <= 1; ++tmp) {
+                byte[] expected = new byte[bytes.length];
+                System.arraycopy(bytes, 0, expected, 0, bytes.length);
+                if (tmp != 0) {
+                    expected[offset / Byte.SIZE] |= (byte) (1 << (offset % Byte.SIZE));
+                } else {
+                    expected[offset / Byte.SIZE] &= (byte) (~(1 << (offset % Byte.SIZE)));
+                }
+                testSetBit(bytes, offset, tmp, PBinary.INSTANCE, expected);
+            }
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/caf65ca7/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java b/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
index 96b8ea2..5265afc 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
@@ -23,6 +23,7 @@ import static org.apache.phoenix.util.PhoenixRuntime.JDBC_PROTOCOL_TERMINATOR;
 import static org.apache.phoenix.util.PhoenixRuntime.PHOENIX_TEST_DRIVER_URL_PARAM;
 import static org.apache.phoenix.util.TestUtil.ATABLE_NAME;
 import static org.apache.phoenix.util.TestUtil.A_VALUE;
+import static org.apache.phoenix.util.TestUtil.BINARY_NAME;
 import static org.apache.phoenix.util.TestUtil.BTABLE_NAME;
 import static org.apache.phoenix.util.TestUtil.B_VALUE;
 import static org.apache.phoenix.util.TestUtil.CUSTOM_ENTITY_DATA_FULL_NAME;
@@ -458,6 +459,13 @@ public abstract class BaseTest {
                 "    co_item_name varchar " +
                 "   CONSTRAINT pk PRIMARY KEY (item_id, item_name)) " +
                 "   SALT_BUCKETS=4");
+        builder.put(BINARY_NAME,"create table " + BINARY_NAME +
+            "   (a_binary BINARY(16) not null, \n" +
+            "    b_binary BINARY(16), \n" +
+            "    a_varbinary VARBINARY, \n" +
+            "    b_varbinary VARBINARY, \n" +
+            "    CONSTRAINT pk PRIMARY KEY (a_binary)\n" +
+            ") ");
         tableDDLMap = builder.build();
     }
     

http://git-wip-us.apache.org/repos/asf/phoenix/blob/caf65ca7/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java b/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
index 15e3583..1d56dba 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
@@ -207,6 +207,7 @@ public class TestUtil {
     public static final String JOIN_ITEM_TABLE_DISPLAY_NAME = JOIN_SCHEMA + "." + JOIN_ITEM_TABLE;
     public static final String JOIN_SUPPLIER_TABLE_DISPLAY_NAME = JOIN_SCHEMA + "." + JOIN_SUPPLIER_TABLE;
     public static final String JOIN_COITEM_TABLE_DISPLAY_NAME = JOIN_SCHEMA + "." + JOIN_COITEM_TABLE;
+    public static final String BINARY_NAME = "BinaryTable";
 
     /**
      * Read-only properties used by all tests


[04/40] phoenix git commit: PHOENIX-2115 Simplify Pherf generated dependency jar and pom.xml

Posted by ma...@apache.org.
PHOENIX-2115 Simplify Pherf generated dependency jar and pom.xml


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/6277fdaf
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/6277fdaf
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/6277fdaf

Branch: refs/heads/calcite
Commit: 6277fdafc0e8ac0e2e74df540dc1a924165faf22
Parents: 359c255
Author: Mujtaba <mu...@apache.org>
Authored: Tue Jul 21 15:57:04 2015 -0700
Committer: Mujtaba <mu...@apache.org>
Committed: Tue Jul 21 15:57:04 2015 -0700

----------------------------------------------------------------------
 phoenix-pherf/cluster/pherf.sh                  |   4 +-
 phoenix-pherf/config/env.sh                     |   4 +-
 phoenix-pherf/pom.xml                           | 527 ++++++-------------
 phoenix-pherf/src/main/assembly/cluster.xml     |   5 +-
 .../src/main/assembly/components-minimal.xml    |  33 ++
 phoenix-pherf/src/main/assembly/minimal.xml     |  31 ++
 phoenix-pherf/src/main/assembly/standalone.xml  |  13 +-
 7 files changed, 247 insertions(+), 370 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/6277fdaf/phoenix-pherf/cluster/pherf.sh
----------------------------------------------------------------------
diff --git a/phoenix-pherf/cluster/pherf.sh b/phoenix-pherf/cluster/pherf.sh
index 8d58dfe..2e0913e 100755
--- a/phoenix-pherf/cluster/pherf.sh
+++ b/phoenix-pherf/cluster/pherf.sh
@@ -17,7 +17,7 @@
 #  limitations under the License.
 
 source config/env.sh
-HBASE_CLASSPATH=`$HBASE_ROOT/hbase/hbase/bin/hbase classpath`
+HBASE_CLASSPATH=`$HBASE_PATH/bin/hbase classpath`
 
 
 PHERF_HOME=$(cd "`dirname $0`" && pwd)
@@ -30,4 +30,4 @@ done
 
 CMD="time ${JAVA_HOME}/bin/java ${REMOTE_DEBUG} -Dapp.home=${PHERF_HOME} ${ENV_PROPS} -Xms512m -Xmx3072m -cp ${CLASSPATH} org.apache.phoenix.pherf.Pherf ${@}"
 
-eval $CMD
\ No newline at end of file
+eval $CMD

http://git-wip-us.apache.org/repos/asf/phoenix/blob/6277fdaf/phoenix-pherf/config/env.sh
----------------------------------------------------------------------
diff --git a/phoenix-pherf/config/env.sh b/phoenix-pherf/config/env.sh
index 0979415..b8115b6 100644
--- a/phoenix-pherf/config/env.sh
+++ b/phoenix-pherf/config/env.sh
@@ -19,11 +19,11 @@
 # Required variable to point to Java installation
 JAVA_HOME=
 
-# Absolute path the the unzipped root directory of the HBase installation
+# Absolute path the the unzipped directory of the HBase installation
 # This is required if you build using the default or cluster profile
 # Cluster profile assumes you want to pick up dependencies from HBase classpath
 # Not required in standalone.
-HBASE_ROOT=
+HBASE_PATH=
 
 # Add a space seperated list of -D environment args. "-Dkey1-val1 -Dkey2=val2"
 ENV_PROPS=""

http://git-wip-us.apache.org/repos/asf/phoenix/blob/6277fdaf/phoenix-pherf/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-pherf/pom.xml b/phoenix-pherf/pom.xml
index 4d27305..3817b3a 100644
--- a/phoenix-pherf/pom.xml
+++ b/phoenix-pherf/pom.xml
@@ -1,364 +1,179 @@
-<!--
-  ~ 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.
-  -->
+<!-- ~ 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. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.phoenix</groupId>
+		<artifactId>phoenix</artifactId>
+		<version>4.5.0-SNAPSHOT</version>
+	</parent>
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.phoenix</groupId>
-        <artifactId>phoenix</artifactId>
-        <version>4.5.0-SNAPSHOT</version>
-    </parent>
+	<artifactId>phoenix-pherf</artifactId>
+	<packaging>jar</packaging>
+	<name>Phoenix - Pherf</name>
 
-    <artifactId>phoenix-pherf</artifactId>
-    <packaging>jar</packaging>
-    <name>Phoenix - Pherf</name>
+	<properties>
+		<top.dir>${project.basedir}/..</top.dir>
+	</properties>
 
-    <properties>
-        <top.dir>${project.basedir}/..</top.dir>
-    </properties>
+	<repositories>
+		<repository>
+			<id>apache release</id>
+			<url>https://repository.apache.org/content/repositories/releases/</url>
+		</repository>
+	</repositories>
 
-    <profiles>
-        <profile>
-            <id>standalone</id>
-            <activation>
-                <activeByDefault>true</activeByDefault>
-            </activation>
-            <build>
-                <resources>
-                    <resource>
-                        <directory>src/main/resources</directory>
-                    </resource>
-                </resources>
-                <testResources>
-                    <testResource>
-                        <directory>src/test/resources</directory>
-                    </testResource>
-                    <testResource>
-                        <directory>${project.basedir}/config</directory>
-                    </testResource>
-                </testResources>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-resources-plugin</artifactId>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-assembly-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>make-dependency-jar</id>
-                                <phase>package</phase>
-                                <goals>
-                                    <goal>single</goal>
-                                </goals>
-                                <configuration>
-                                    <descriptorRefs>
-                                        <descriptorRef>jar-with-dependencies</descriptorRef>
-                                    </descriptorRefs>
-                                    <archive>
-                                        <manifest>
-                                            <mainClass>org.apache.phoenix.pherf.Pherf</mainClass>
-                                        </manifest>
-                                    </archive>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>make-assembly</id>
-                                <phase>package</phase>
-                                <goals>
-                                    <goal>single</goal>
-                                </goals>
-                                <configuration>
-                                    <descriptors>
-                                        <descriptor>src/main/assembly/standalone.xml</descriptor>
-                                    </descriptors>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.phoenix</groupId>
+			<artifactId>phoenix-core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.phoenix</groupId>
+			<artifactId>phoenix-core</artifactId>
+			<classifier>tests</classifier>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.jfree</groupId>
+			<artifactId>jfreechart</artifactId>
+			<version>1.0.19</version>
+		</dependency>
+		<dependency>
+			<groupId>com.googlecode.java-diff-utils</groupId>
+			<artifactId>diffutils</artifactId>
+			<version>1.2.1</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-lang3</artifactId>
+			<version>3.3.2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-math3</artifactId>
+			<version>3.3</version>
+		</dependency>
 
-        <profile>
-            <!-- default: creates a bundle for running on an SFDC cluster node as the 'sfdc' user -->
-            <id>cluster</id>
-            <activation>
-                <activeByDefault>true</activeByDefault>
-            </activation>
-            <build>
-                <resources>
-                    <resource>
-                        <directory>src/main/resources</directory>
-                    </resource>
-                </resources>
-                <testResources>
-                    <testResource>
-                        <directory>src/test/resources</directory>
-                    </testResource>
-                    <testResource>
-                        <directory>${project.basedir}/config</directory>
-                    </testResource>
-                </testResources>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-resources-plugin</artifactId>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-assembly-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>make-dependency-jar</id>
-                                <phase>package</phase>
-                                <goals>
-                                    <goal>single</goal>
-                                </goals>
-                                <configuration>
-                                    <descriptorRefs>
-                                        <descriptorRef>jar-with-dependencies</descriptorRef>
-                                    </descriptorRefs>
-                                    <archive>
-                                        <manifest>
-                                            <mainClass>org.apache.phoenix.pherf.Pherf</mainClass>
-                                        </manifest>
-                                    </archive>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>make-assembly</id>
-                                <phase>package</phase>
-                                <goals>
-                                    <goal>single</goal>
-                                </goals>
-                                <configuration>
-                                    <descriptors>
-                                        <descriptor>src/main/assembly/cluster.xml</descriptor>
-                                    </descriptors>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
+		<!-- Test Dependencies -->
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.11</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>com.jcabi</groupId>
+			<artifactId>jcabi-jdbc</artifactId>
+			<version>0.15</version>
+		</dependency>
+		<dependency>
+			<groupId>org.hamcrest</groupId>
+			<artifactId>hamcrest-junit</artifactId>
+			<version>1.0.0.0</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>com.github.stefanbirkner</groupId>
+			<artifactId>system-rules</artifactId>
+			<version>1.8.0</version>
+		</dependency>
+	</dependencies>
 
-    </profiles>
-    <repositories>
-        <repository>
-            <id>apache release</id>
-            <url>https://repository.apache.org/content/repositories/releases/</url>
-        </repository>
-    </repositories>
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.phoenix</groupId>
-            <artifactId>phoenix-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.phoenix</groupId>
-            <artifactId>phoenix-core</artifactId>
-            <classifier>tests</classifier>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-            <version>14.0.1</version>
-        </dependency>
-        <dependency>
-            <groupId>commons-io</groupId>
-            <artifactId>commons-io</artifactId>
-            <version>2.4</version>
-        </dependency>
-        <dependency>
-            <groupId>commons-cli</groupId>
-            <artifactId>commons-cli</artifactId>
-            <version>1.2</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-            <version>3.3.2</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-math3</artifactId>
-            <version>3.3</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jfree</groupId>
-            <artifactId>jfreechart</artifactId>
-            <version>1.0.19</version>
-        </dependency>
-        <dependency>
-            <groupId>joda-time</groupId>
-            <artifactId>joda-time</artifactId>
-            <version>${jodatime.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.googlecode.java-diff-utils</groupId>
-            <artifactId>diffutils</artifactId>
-            <version>1.2.1</version>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-log4j12</artifactId>
-            <version>1.7.10</version>
-        </dependency>
+	<build>
+		<resources>
+			<resource>
+				<directory>src/main/resources</directory>
+			</resource>
+		</resources>
+		<testResources>
+			<testResource>
+				<directory>src/test/resources</directory>
+			</testResource>
+			<testResource>
+				<directory>${project.basedir}/config</directory>
+			</testResource>
+		</testResources>
+		<plugins>
+			<plugin>
+				<groupId>org.codehaus.mojo</groupId>
+				<artifactId>build-helper-maven-plugin</artifactId>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-failsafe-plugin</artifactId>
+			</plugin>
+			<plugin>
+				<artifactId>maven-dependency-plugin</artifactId>
+				<version>${maven-dependency-plugin.version}</version>
+			</plugin>
 
-        <!-- Test Dependencies -->
-        <dependency>
-            <groupId>com.jcabi</groupId>
-            <artifactId>jcabi-jdbc</artifactId>
-            <version>0.15</version>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>4.11</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-junit</artifactId>
-            <version>1.0.0.0</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.github.stefanbirkner</groupId>
-            <artifactId>system-rules</artifactId>
-            <version>1.8.0</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hbase</groupId>
-            <artifactId>hbase-testing-util</artifactId>
-            <version>${hbase.version}</version>
-            <scope>test</scope>
-            <optional>true</optional>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.jruby</groupId>
-                    <artifactId>jruby-complete</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hbase</groupId>
-            <artifactId>hbase-it</artifactId>
-            <version>${hbase.version}</version>
-            <type>test-jar</type>
-            <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.jruby</groupId>
-                    <artifactId>jruby-complete</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hbase</groupId>
-            <artifactId>hbase-common</artifactId>
-            <version>${hbase.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hbase</groupId>
-            <artifactId>hbase-protocol</artifactId>
-            <version>${hbase.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hbase</groupId>
-            <artifactId>hbase-client</artifactId>
-            <version>${hbase.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hbase</groupId>
-            <artifactId>hbase-hadoop-compat</artifactId>
-            <version>${hbase.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hbase</groupId>
-            <artifactId>hbase-hadoop-compat</artifactId>
-            <version>${hbase.version}</version>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hbase</groupId>
-            <artifactId>hbase-hadoop2-compat</artifactId>
-            <version>${hbase.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hbase</groupId>
-            <artifactId>hbase-hadoop2-compat</artifactId>
-            <version>${hbase.version}</version>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hadoop</groupId>
-            <artifactId>hadoop-common</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hadoop</groupId>
-            <artifactId>hadoop-mapreduce-client-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hadoop</groupId>
-            <artifactId>hadoop-minicluster</artifactId>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>build-helper-maven-plugin</artifactId>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-failsafe-plugin</artifactId>
-            </plugin>
-            <plugin>
-                <artifactId>maven-dependency-plugin</artifactId>
-                <version>${maven-dependency-plugin.version}</version>
-            </plugin>
-
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <version>3.1</version>
-                <configuration>
-                    <source>1.7</source>
-                    <target>1.7</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>3.1</version>
+				<configuration>
+					<source>1.7</source>
+					<target>1.7</target>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-surefire-plugin</artifactId>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-resources-plugin</artifactId>
+			</plugin>
+			<plugin>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<executions>
+					<execution>
+						<id>make-dependency-jar</id>
+						<phase>package</phase>
+						<goals>
+							<goal>single</goal>
+						</goals>
+						<configuration>
+							<descriptorRefs>
+								<descriptorRef>jar-with-dependencies</descriptorRef>
+							</descriptorRefs>
+							<archive>
+								<manifest>
+									<mainClass>org.apache.phoenix.pherf.Pherf</mainClass>
+								</manifest>
+							</archive>
+						</configuration>
+					</execution>
+					<execution>
+						<id>make-assembly</id>
+						<phase>package</phase>
+						<goals>
+							<goal>single</goal>
+						</goals>
+						<configuration>
+							<descriptors>
+							    <!-- Produces minimal Pherf jar -->
+								<descriptor>src/main/assembly/minimal.xml</descriptor>
+								<!-- Produces standalone zip that bundles all required dependencies -->
+								<descriptor>src/main/assembly/standalone.xml</descriptor>
+								<!-- Produces cluster zip with minimal Pherf jar. Setting HBase classpath in env.sh is required for this configuration -->								
+								<descriptor>src/main/assembly/cluster.xml</descriptor>
+							</descriptors>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
 </project>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/6277fdaf/phoenix-pherf/src/main/assembly/cluster.xml
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/assembly/cluster.xml b/phoenix-pherf/src/main/assembly/cluster.xml
index 961240a..c870309 100644
--- a/phoenix-pherf/src/main/assembly/cluster.xml
+++ b/phoenix-pherf/src/main/assembly/cluster.xml
@@ -38,15 +38,14 @@
             <outputDirectory>pherf-${project.version}-cluster/</outputDirectory>
             <includes>
                 <include>*sh</include>
-                <include>*dependencies.jar</include>
             </includes>
         </fileSet>
         <fileSet>
             <directory>${project.build.directory}</directory>
             <outputDirectory>pherf-${project.version}-cluster/lib</outputDirectory>
             <includes>
-                <include>*dependencies.jar</include>
+                <include>*minimal.jar</include>
             </includes>
         </fileSet>
     </fileSets>
-</assembly>
\ No newline at end of file
+</assembly>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/6277fdaf/phoenix-pherf/src/main/assembly/components-minimal.xml
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/assembly/components-minimal.xml b/phoenix-pherf/src/main/assembly/components-minimal.xml
new file mode 100644
index 0000000..38c6929
--- /dev/null
+++ b/phoenix-pherf/src/main/assembly/components-minimal.xml
@@ -0,0 +1,33 @@
+<!--
+  ~ 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.
+  -->
+
+<component>
+  <dependencySets>
+    <dependencySet>
+      <unpack>true</unpack>
+      <outputDirectory>/</outputDirectory>
+      <includes>
+        <include>org.apache.phoenix:phoenix-pherf</include>
+        <include>org.jfree:jfreechart</include>
+        <include>com.googlecode.java-diff-utils:diffutils</include>
+        <include>org.apache.commons:commons-lang3</include>
+        <include>org.apache.commons:commons-math3</include>
+      </includes>
+    </dependencySet>
+  </dependencySets>
+</component>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/6277fdaf/phoenix-pherf/src/main/assembly/minimal.xml
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/assembly/minimal.xml b/phoenix-pherf/src/main/assembly/minimal.xml
new file mode 100644
index 0000000..5b1f482
--- /dev/null
+++ b/phoenix-pherf/src/main/assembly/minimal.xml
@@ -0,0 +1,31 @@
+<!--
+  ~ 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.
+  -->
+
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+    <id>minimal</id>
+    <baseDirectory>/</baseDirectory>
+    <formats>
+        <format>jar</format>
+    </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <componentDescriptors>
+    <componentDescriptor>src/main/assembly/components-minimal.xml</componentDescriptor>
+  </componentDescriptors>
+</assembly>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/6277fdaf/phoenix-pherf/src/main/assembly/standalone.xml
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/assembly/standalone.xml b/phoenix-pherf/src/main/assembly/standalone.xml
index 7163427..dfeb921 100644
--- a/phoenix-pherf/src/main/assembly/standalone.xml
+++ b/phoenix-pherf/src/main/assembly/standalone.xml
@@ -40,13 +40,12 @@
                 <include>*sh</include>
             </includes>
         </fileSet>
-    </fileSets>
-    <dependencySets>
-        <dependencySet>
-            <unpack>false</unpack>
+        <fileSet>
+            <directory>${project.build.directory}</directory>
             <outputDirectory>pherf-${project.version}-standalone/lib</outputDirectory>
             <includes>
+                <include>*dependencies.jar</include>
             </includes>
-        </dependencySet>
-    </dependencySets>
-</assembly>
\ No newline at end of file
+        </fileSet>
+    </fileSets>
+</assembly>


[39/40] phoenix git commit: Remove calcite staging repo.

Posted by ma...@apache.org.
Remove calcite staging repo.


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/aa26d848
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/aa26d848
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/aa26d848

Branch: refs/heads/calcite
Commit: aa26d848e613649873b90d2fd456d6bc11191b42
Parents: 35bd148
Author: maryannxue <we...@intel.com>
Authored: Sun Aug 23 12:27:23 2015 -0400
Committer: maryannxue <we...@intel.com>
Committed: Sun Aug 23 12:27:23 2015 -0400

----------------------------------------------------------------------
 pom.xml | 4 ----
 1 file changed, 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa26d848/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index fbdf9de..6742f59 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,10 +57,6 @@
         <enabled>true</enabled>
       </snapshots>
     </repository>
-    <repository>
-      <id>apache calcite</id>
-      <url>https://repository.apache.org/content/repositories/orgapachecalcite-1008</url>
-    </repository>
   </repositories>
 
   <parent>


[33/40] phoenix git commit: PHOENIX-2165 Make zip file name and directory consistent for phoenix-*-cluster.zip (gliptak)

Posted by ma...@apache.org.
PHOENIX-2165 Make zip file name and directory consistent for phoenix-*-cluster.zip (gliptak)


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/b28686fd
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/b28686fd
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/b28686fd

Branch: refs/heads/calcite
Commit: b28686fdb685e6c91b73d3494ade19da2f2b47d5
Parents: 209b45e
Author: Mujtaba <mu...@apache.org>
Authored: Thu Aug 13 10:38:55 2015 -0700
Committer: Mujtaba <mu...@apache.org>
Committed: Thu Aug 13 10:38:55 2015 -0700

----------------------------------------------------------------------
 phoenix-pherf/src/main/assembly/cluster.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/b28686fd/phoenix-pherf/src/main/assembly/cluster.xml
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/assembly/cluster.xml b/phoenix-pherf/src/main/assembly/cluster.xml
index c870309..8e690b7 100644
--- a/phoenix-pherf/src/main/assembly/cluster.xml
+++ b/phoenix-pherf/src/main/assembly/cluster.xml
@@ -27,7 +27,7 @@
     <fileSets>
         <fileSet>
             <directory>${project.basedir}/config</directory>
-            <outputDirectory>pherf-${project.version}-cluster/config</outputDirectory>
+            <outputDirectory>phoenix-pherf-${project.version}-cluster/config</outputDirectory>
             <includes>
                 <include>*/*</include>
                 <include>*</include>
@@ -35,14 +35,14 @@
         </fileSet>
         <fileSet>
             <directory>${project.basedir}/cluster</directory>
-            <outputDirectory>pherf-${project.version}-cluster/</outputDirectory>
+            <outputDirectory>phoenix-pherf-${project.version}-cluster/</outputDirectory>
             <includes>
                 <include>*sh</include>
             </includes>
         </fileSet>
         <fileSet>
             <directory>${project.build.directory}</directory>
-            <outputDirectory>pherf-${project.version}-cluster/lib</outputDirectory>
+            <outputDirectory>phoenix-pherf-${project.version}-cluster/lib</outputDirectory>
             <includes>
                 <include>*minimal.jar</include>
             </includes>


[10/40] phoenix git commit: PHOENIX-2110 Primary key changes should be pushed to diverged views

Posted by ma...@apache.org.
PHOENIX-2110 Primary key changes should be pushed to diverged views


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/5b46793b
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/5b46793b
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/5b46793b

Branch: refs/heads/calcite
Commit: 5b46793b6951cf1ca04850a5ad771f2cd9f5802a
Parents: 498cc55
Author: Samarth <sa...@salesforce.com>
Authored: Wed Jul 22 11:46:05 2015 -0700
Committer: Samarth <sa...@salesforce.com>
Committed: Wed Jul 22 11:46:05 2015 -0700

----------------------------------------------------------------------
 .../apache/phoenix/end2end/AlterTableIT.java    |  929 +---------------
 .../phoenix/end2end/AlterTableWithViewsIT.java  | 1047 ++++++++++++++++++
 .../coprocessor/MetaDataEndpointImpl.java       |  755 ++++++++-----
 3 files changed, 1536 insertions(+), 1195 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/5b46793b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
index 1758dd4..4053301 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
@@ -18,7 +18,6 @@
 package org.apache.phoenix.end2end;
 
 import static org.apache.hadoop.hbase.HColumnDescriptor.DEFAULT_REPLICATION_SCOPE;
-import static org.apache.phoenix.exception.SQLExceptionCode.CANNOT_MUTATE_TABLE;
 import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
 import static org.apache.phoenix.util.TestUtil.closeConnection;
 import static org.apache.phoenix.util.TestUtil.closeStatement;
@@ -33,11 +32,9 @@ import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.Collections;
-import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 
@@ -46,17 +43,13 @@ import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.KeepDeletedCells;
 import org.apache.hadoop.hbase.client.HBaseAdmin;
 import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.phoenix.compile.QueryPlan;
 import org.apache.phoenix.coprocessor.MetaDataProtocol;
 import org.apache.phoenix.exception.SQLExceptionCode;
 import org.apache.phoenix.jdbc.PhoenixConnection;
 import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
-import org.apache.phoenix.jdbc.PhoenixStatement;
 import org.apache.phoenix.query.QueryConstants;
-import org.apache.phoenix.schema.PColumn;
 import org.apache.phoenix.schema.PTable;
 import org.apache.phoenix.schema.PTableKey;
-import org.apache.phoenix.schema.PTableType;
 import org.apache.phoenix.schema.TableNotFoundException;
 import org.apache.phoenix.util.IndexUtil;
 import org.apache.phoenix.util.PhoenixRuntime;
@@ -66,8 +59,6 @@ import org.apache.phoenix.util.SchemaUtil;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import com.google.common.base.Objects;
-
 /**
  *
  * A lot of tests in this class test HBase level properties. As a result,
@@ -2007,923 +1998,5 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
             conn.close();
         }
     }
-    
-    @Test
-    public void testAddNewColumnsToBaseTableWithViews() throws Exception {
-        Connection conn = DriverManager.getConnection(getUrl());
-        try {       
-            conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
-                    + " ID char(1) NOT NULL,"
-                    + " COL1 integer NOT NULL,"
-                    + " COL2 bigint NOT NULL,"
-                    + " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
-                    + " )");
-            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
-            
-            conn.createStatement().execute("CREATE VIEW VIEWOFTABLE ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR ) AS SELECT * FROM TABLEWITHVIEW");
-            assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
-            
-            // adding a new pk column and a new regular column
-            conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD COL3 varchar(10) PRIMARY KEY, COL4 integer");
-            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 5, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2", "COL3", "COL4");
-            assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 7, 5, "ID", "COL1", "COL2", "COL3", "COL4", "VIEW_COL1", "VIEW_COL2");
-        } finally {
-            conn.close();
-        }
-    }
-    
-    @Test
-    public void testAddExistingViewColumnToBaseTableWithViews() throws Exception {
-        Connection conn = DriverManager.getConnection(getUrl());
-        try {       
-            conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
-                    + " ID char(10) NOT NULL,"
-                    + " COL1 integer NOT NULL,"
-                    + " COL2 bigint NOT NULL,"
-                    + " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
-                    + " )");
-            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
-            
-            conn.createStatement().execute("CREATE VIEW VIEWOFTABLE ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256), VIEW_COL3 VARCHAR, VIEW_COL4 DECIMAL, VIEW_COL5 DECIMAL(10,2), VIEW_COL6 VARCHAR, CONSTRAINT pk PRIMARY KEY (VIEW_COL5, VIEW_COL6) ) AS SELECT * FROM TABLEWITHVIEW");
-            assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 9, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2", "VIEW_COL3", "VIEW_COL4", "VIEW_COL5", "VIEW_COL6");
-            
-            // upsert single row into view
-            String dml = "UPSERT INTO VIEWOFTABLE VALUES(?,?,?,?,?, ?, ?, ?, ?)";
-            PreparedStatement stmt = conn.prepareStatement(dml);
-            stmt.setString(1, "view1");
-            stmt.setInt(2, 12);
-            stmt.setInt(3, 13);
-            stmt.setInt(4, 14);
-            stmt.setString(5, "view5");
-            stmt.setString(6, "view6");
-            stmt.setInt(7, 17);
-            stmt.setInt(8, 18);
-            stmt.setString(9, "view9");
-            stmt.execute();
-            conn.commit();
-            
-            try {
-            	// should fail because there is already a view column with same name of different type
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 char(10)");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }           
-            
-            try {
-            	// should fail because there is already a view column with same name with different scale
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,1)");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            } 
-            
-            try {
-            	// should fail because there is already a view column with same name with different length
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(9,2)");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            } 
-            
-            try {
-            	// should fail because there is already a view column with different length
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }
-            
-            // validate that there were no columns added to the table or view
-            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
-            assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 9, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2", "VIEW_COL3", "VIEW_COL4", "VIEW_COL5", "VIEW_COL6");
-            
-            // should succeed 
-            conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL4 DECIMAL, VIEW_COL2 VARCHAR(256)");
-            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 5, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2", "VIEW_COL4", "VIEW_COL2");
-            assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 9, 5, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2", "VIEW_COL3", "VIEW_COL4", "VIEW_COL5", "VIEW_COL6");
-            
-            // query table
-            ResultSet rs = stmt.executeQuery("SELECT * FROM TABLEWITHVIEW");
-            assertTrue(rs.next());
-            assertEquals("view1", rs.getString("ID"));
-            assertEquals(12, rs.getInt("COL1"));
-            assertEquals(13, rs.getInt("COL2"));
-            assertEquals("view5", rs.getString("VIEW_COL2"));
-            assertEquals(17, rs.getInt("VIEW_COL4"));
-            assertFalse(rs.next());
-
-            // query view
-            rs = stmt.executeQuery("SELECT * FROM VIEWOFTABLE");
-            assertTrue(rs.next());
-            assertEquals("view1", rs.getString("ID"));
-            assertEquals(12, rs.getInt("COL1"));
-            assertEquals(13, rs.getInt("COL2"));
-            assertEquals(14, rs.getInt("VIEW_COL1"));
-            assertEquals("view5", rs.getString("VIEW_COL2"));
-            assertEquals("view6", rs.getString("VIEW_COL3"));
-            assertEquals(17, rs.getInt("VIEW_COL4"));
-            assertEquals(18, rs.getInt("VIEW_COL5"));
-            assertEquals("view9", rs.getString("VIEW_COL6"));
-            assertFalse(rs.next());
-        } finally {
-            conn.close();
-        }
-    }
-    
-    @Test
-    public void testAddExistingViewPkColumnToBaseTableWithViews() throws Exception {
-        Connection conn = DriverManager.getConnection(getUrl());
-        try {       
-            conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
-                    + " ID char(10) NOT NULL,"
-                    + " COL1 integer NOT NULL,"
-                    + " COL2 integer NOT NULL,"
-                    + " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
-                    + " )");
-            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
-            
-            conn.createStatement().execute("CREATE VIEW VIEWOFTABLE ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) CONSTRAINT pk PRIMARY KEY (VIEW_COL1, VIEW_COL2)) AS SELECT * FROM TABLEWITHVIEW");
-            assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
-            
-            // upsert single row into view
-            String dml = "UPSERT INTO VIEWOFTABLE VALUES(?,?,?,?,?)";
-            PreparedStatement stmt = conn.prepareStatement(dml);
-            stmt.setString(1, "view1");
-            stmt.setInt(2, 12);
-            stmt.setInt(3, 13);
-            stmt.setInt(4, 14);
-            stmt.setString(5, "view5");
-            stmt.execute();
-            conn.commit();
-            
-            try {
-            	// should fail because there we have to add both VIEW_COL1 and VIEW_COL2 to the pk
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR(256) PRIMARY KEY");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }
-            
-            try {
-            	// should fail because there we have to add both VIEW_COL1 and VIEW_COL2  to the pk 
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }
-            
-            try {
-            	// should fail because there we have to add both VIEW_COL1 and VIEW_COL2 to the pk
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) PRIMARY KEY");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }
-            
-            try {
-            	// should fail because there we have to add both VIEW_COL1 and VIEW_COL2  to the pk 
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY, VIEW_COL2 VARCHAR(256)");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }
-            
-            try {
-            	// should fail because there we have to add both VIEW_COL1 and VIEW_COL2 to the pk in the right order
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR(256) PRIMARY KEY, VIEW_COL1 DECIMAL(10,2) PRIMARY KEY");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }
-            
-            try {
-            	// should fail because there we have to add both VIEW_COL1 and VIEW_COL2 with the right sort order
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY DESC, VIEW_COL2 VARCHAR(256) PRIMARY KEY");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }
-            
-            // add the pk column of the view to the base table
-            conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY, VIEW_COL2 VARCHAR(256) PRIMARY KEY");
-            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 5, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
-            assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 5, 5, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
-            
-            // query table
-            ResultSet rs = stmt.executeQuery("SELECT * FROM TABLEWITHVIEW");
-            assertTrue(rs.next());
-            assertEquals("view1", rs.getString("ID"));
-            assertEquals(12, rs.getInt("COL1"));
-            assertEquals(13, rs.getInt("COL2"));
-            assertEquals(14, rs.getInt("VIEW_COL1"));
-            assertEquals("view5", rs.getString("VIEW_COL2"));
-            assertFalse(rs.next());
-
-            // query view
-            rs = stmt.executeQuery("SELECT * FROM VIEWOFTABLE");
-            assertTrue(rs.next());
-            assertEquals("view1", rs.getString("ID"));
-            assertEquals(12, rs.getInt("COL1"));
-            assertEquals(13, rs.getInt("COL2"));
-            assertEquals(14, rs.getInt("VIEW_COL1"));
-            assertEquals("view5", rs.getString("VIEW_COL2"));
-            assertFalse(rs.next());
-        } finally {
-            conn.close();
-        }
-    }
-    
-    @Test
-    public void testAddExistingViewPkColumnToBaseTableWithMultipleViews() throws Exception {
-        Connection conn = DriverManager.getConnection(getUrl());
-        try {       
-            conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
-                    + " ID char(10) NOT NULL,"
-                    + " COL1 integer NOT NULL,"
-                    + " COL2 integer NOT NULL,"
-                    + " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
-                    + " )");
-            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
-            
-            conn.createStatement().execute("CREATE VIEW VIEWOFTABLE1 ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) CONSTRAINT pk PRIMARY KEY (VIEW_COL1, VIEW_COL2)) AS SELECT * FROM TABLEWITHVIEW");
-            assertTableDefinition(conn, "VIEWOFTABLE1", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
-            
-            conn.createStatement().execute("CREATE VIEW VIEWOFTABLE2 ( VIEW_COL3 VARCHAR(256), VIEW_COL4 DECIMAL(10,2) CONSTRAINT pk PRIMARY KEY (VIEW_COL3, VIEW_COL4)) AS SELECT * FROM TABLEWITHVIEW");
-            assertTableDefinition(conn, "VIEWOFTABLE2", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL3", "VIEW_COL4");
-            
-            try {
-            	// should fail because there are two view with different pk columns
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL PRIMARY KEY, VIEW_COL2 VARCHAR PRIMARY KEY");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }
-            
-            try {
-            	// should fail because there are two view with different pk columns
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL3 VARCHAR PRIMARY KEY, VIEW_COL4 DECIMAL PRIMARY KEY");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }
-            
-            try {
-            	// should fail because slot positions of pks are different
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL PRIMARY KEY, VIEW_COL2 VARCHAR PRIMARY KEY, VIEW_COL3 VARCHAR PRIMARY KEY, VIEW_COL4 DECIMAL PRIMARY KEY");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }
-            
-            try {
-            	// should fail because slot positions of pks are different
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL3 VARCHAR PRIMARY KEY, VIEW_COL4 DECIMAL PRIMARY KEY, VIEW_COL1 DECIMAL PRIMARY KEY, VIEW_COL2 VARCHAR PRIMARY KEY");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }
-        } finally {
-            conn.close();
-        }
-    }
-    
-    @Test
-    public void testAddExistingViewPkColumnToBaseTableWithMultipleViewsHavingSamePks() throws Exception {
-        Connection conn = DriverManager.getConnection(getUrl());
-        try {       
-            conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
-                    + " ID char(10) NOT NULL,"
-                    + " COL1 integer NOT NULL,"
-                    + " COL2 integer NOT NULL,"
-                    + " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
-                    + " )");
-            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
-            
-            conn.createStatement().execute("CREATE VIEW VIEWOFTABLE1 ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) CONSTRAINT pk PRIMARY KEY (VIEW_COL1, VIEW_COL2)) AS SELECT * FROM TABLEWITHVIEW");
-            assertTableDefinition(conn, "VIEWOFTABLE1", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
-            
-            conn.createStatement().execute("CREATE VIEW VIEWOFTABLE2 ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) CONSTRAINT pk PRIMARY KEY (VIEW_COL1, VIEW_COL2)) AS SELECT * FROM TABLEWITHVIEW");
-            assertTableDefinition(conn, "VIEWOFTABLE2", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
-            
-            // upsert single row into both view
-            String dml = "UPSERT INTO VIEWOFTABLE1 VALUES(?,?,?,?,?)";
-            PreparedStatement stmt = conn.prepareStatement(dml);
-            stmt.setString(1, "view1");
-            stmt.setInt(2, 12);
-            stmt.setInt(3, 13);
-            stmt.setInt(4, 14);
-            stmt.setString(5, "view5");
-            stmt.execute();
-            conn.commit();
-            dml = "UPSERT INTO VIEWOFTABLE2 VALUES(?,?,?,?,?)";
-            stmt = conn.prepareStatement(dml);
-            stmt.setString(1, "view1");
-            stmt.setInt(2, 12);
-            stmt.setInt(3, 13);
-            stmt.setInt(4, 14);
-            stmt.setString(5, "view5");
-            stmt.execute();
-            conn.commit();
-            
-            try {
-            	// should fail because the view have two extra columns in their pk
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }
-            
-            try {
-            	// should fail because the view have two extra columns in their pk
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR(256) PRIMARY KEY");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }
-            
-            try {
-            	// should fail because slot positions of pks are different
-            	conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 DECIMAL(10,2) PRIMARY KEY, VIEW_COL1 VARCHAR(256) PRIMARY KEY");
-            	fail();
-            }
-            catch (SQLException e) {
-            	assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }
-            
-            conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY, VIEW_COL2 VARCHAR(256) PRIMARY KEY");
-            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 5, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
-            assertTableDefinition(conn, "VIEWOFTABLE1", PTableType.VIEW, "TABLEWITHVIEW", 1, 5, 5, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
-            assertTableDefinition(conn, "VIEWOFTABLE2", PTableType.VIEW, "TABLEWITHVIEW", 1, 5, 5, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
-            
-            // query table
-            ResultSet rs = stmt.executeQuery("SELECT * FROM TABLEWITHVIEW");
-            assertTrue(rs.next());
-            assertEquals("view1", rs.getString("ID"));
-            assertEquals(12, rs.getInt("COL1"));
-            assertEquals(13, rs.getInt("COL2"));
-            assertEquals(14, rs.getInt("VIEW_COL1"));
-            assertEquals("view5", rs.getString("VIEW_COL2"));
-            assertFalse(rs.next());
-
-            // query both views
-            rs = stmt.executeQuery("SELECT * FROM VIEWOFTABLE1");
-            assertTrue(rs.next());
-            assertEquals("view1", rs.getString("ID"));
-            assertEquals(12, rs.getInt("COL1"));
-            assertEquals(13, rs.getInt("COL2"));
-            assertEquals(14, rs.getInt("VIEW_COL1"));
-            assertEquals("view5", rs.getString("VIEW_COL2"));
-            assertFalse(rs.next());
-            rs = stmt.executeQuery("SELECT * FROM VIEWOFTABLE2");
-            assertTrue(rs.next());
-            assertEquals("view1", rs.getString("ID"));
-            assertEquals(12, rs.getInt("COL1"));
-            assertEquals(13, rs.getInt("COL2"));
-            assertEquals(14, rs.getInt("VIEW_COL1"));
-            assertEquals("view5", rs.getString("VIEW_COL2"));
-            assertFalse(rs.next());
-        } finally {
-            conn.close();
-        }
-    }
-    
-    private void assertTableDefinition(Connection conn, String tableName, PTableType tableType, String parentTableName, int sequenceNumber, int columnCount, int baseColumnCount, String... columnName) throws Exception {
-        PreparedStatement p = conn.prepareStatement("SELECT * FROM SYSTEM.CATALOG WHERE TABLE_NAME=? AND TABLE_TYPE=?");
-        p.setString(1, tableName);
-        p.setString(2, tableType.getSerializedValue());
-        ResultSet rs = p.executeQuery();
-        assertTrue(rs.next());
-        assertEquals(getSystemCatalogEntriesForTable(conn, tableName, "Mismatch in BaseColumnCount"), baseColumnCount, rs.getInt("BASE_COLUMN_COUNT"));
-        assertEquals(getSystemCatalogEntriesForTable(conn, tableName, "Mismatch in columnCount"), columnCount, rs.getInt("COLUMN_COUNT"));
-        assertEquals(getSystemCatalogEntriesForTable(conn, tableName, "Mismatch in sequenceNumber"), sequenceNumber, rs.getInt("TABLE_SEQ_NUM"));
-        rs.close();
-
-        ResultSet parentTableColumnsRs = null; 
-        if (parentTableName != null) {
-            parentTableColumnsRs = conn.getMetaData().getColumns(null, null, parentTableName, null);
-            parentTableColumnsRs.next();
-        }
-        
-        ResultSet viewColumnsRs = conn.getMetaData().getColumns(null, null, tableName, null);
-        for (int i = 0; i < columnName.length; i++) {
-            if (columnName[i] != null) {
-                assertTrue(viewColumnsRs.next());
-                assertEquals(getSystemCatalogEntriesForTable(conn, tableName, "Mismatch in columnName: i=" + i), columnName[i], viewColumnsRs.getString(PhoenixDatabaseMetaData.COLUMN_NAME));
-                assertEquals(getSystemCatalogEntriesForTable(conn, tableName, "Mismatch in ordinalPosition: i=" + i), i+1, viewColumnsRs.getInt(PhoenixDatabaseMetaData.ORDINAL_POSITION));
-                // validate that all the columns in the base table are present in the view   
-                if (parentTableColumnsRs != null && !parentTableColumnsRs.isAfterLast()) {
-                    ResultSetMetaData parentTableColumnsMetadata = parentTableColumnsRs.getMetaData();
-                    assertEquals(parentTableColumnsMetadata.getColumnCount(), viewColumnsRs.getMetaData().getColumnCount());
-                    
-                    // if you add a non-pk column that already exists in the view
-                    if (!viewColumnsRs.getString(PhoenixDatabaseMetaData.COLUMN_NAME).equals(parentTableColumnsRs.getString(PhoenixDatabaseMetaData.COLUMN_NAME))) {
-                    	continue;
-                    }
-                    
-                    for (int columnIndex = 1; columnIndex < parentTableColumnsMetadata.getColumnCount(); columnIndex++) {
-                        String viewColumnValue = viewColumnsRs.getString(columnIndex);
-                        String parentTableColumnValue = parentTableColumnsRs.getString(columnIndex);
-                        if (!Objects.equal(viewColumnValue, parentTableColumnValue)) {
-                            if (parentTableColumnsMetadata.getColumnName(columnIndex).equals(PhoenixDatabaseMetaData.TABLE_NAME)) {
-                                assertEquals(parentTableName, parentTableColumnValue);
-                                assertEquals(tableName, viewColumnValue);
-                            } 
-                            // its ok if the ordinal positions don't match for non-pk columns
-                            else if (!(parentTableColumnsMetadata.getColumnName(columnIndex).equals(PhoenixDatabaseMetaData.ORDINAL_POSITION) && parentTableColumnsRs.getString(PhoenixDatabaseMetaData.COLUMN_FAMILY)!=null)) {
-                                fail(parentTableColumnsMetadata.getColumnName(columnIndex) + " of base table " + parentTableColumnValue + " does not match view "+viewColumnValue) ;
-                            }
-                        }
-                    }
-                    parentTableColumnsRs.next();
-                }
-            }
-        }
-        assertFalse(getSystemCatalogEntriesForTable(conn, tableName, ""), viewColumnsRs.next());
-    }
-    
-    private String getSystemCatalogEntriesForTable(Connection conn, String tableName, String message) throws Exception {
-        StringBuilder sb = new StringBuilder(message);
-        sb.append("\n\n\n");
-        ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM SYSTEM.CATALOG WHERE TABLE_NAME='"+ tableName +"'");
-        ResultSetMetaData metaData = rs.getMetaData();
-        int rowNum = 0;
-        while (rs.next()) {
-            sb.append(rowNum++).append("------\n");
-            for (int i = 1; i <= metaData.getColumnCount(); i++) {
-                sb.append("\t").append(metaData.getColumnLabel(i)).append("=").append(rs.getString(i)).append("\n");
-            }
-            sb.append("\n");
-        }
-        rs.close();
-        return sb.toString();
-    }
-    
-    @Test
-    public void testCacheInvalidatedAfterAddingColumnToBaseTableWithViews() throws Exception {
-        String baseTable = "testCacheInvalidatedAfterAddingColumnToBaseTableWithViews";
-        String viewName = baseTable + "_view";
-        String tenantId = "tenantId";
-        try (Connection globalConn = DriverManager.getConnection(getUrl())) {
-            String tableDDL = "CREATE TABLE " + baseTable + " (TENANT_ID VARCHAR NOT NULL, PK1 VARCHAR NOT NULL, V1 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, PK1)) MULTI_TENANT = true " ;
-            globalConn.createStatement().execute(tableDDL);
-            Properties tenantProps = new Properties();
-            tenantProps.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, tenantId);
-            // create a tenant specific view
-            try (Connection tenantConn =  DriverManager.getConnection(getUrl(), tenantProps)) {
-                String viewDDL = "CREATE VIEW " + viewName + " AS SELECT * FROM " + baseTable;
-                tenantConn.createStatement().execute(viewDDL);
-                
-                // Add a column to the base table using global connection
-                globalConn.createStatement().execute("ALTER TABLE " + baseTable + " ADD NEW_COL VARCHAR");
-
-                // Check now whether the tenant connection can see the column that was added
-                tenantConn.createStatement().execute("SELECT NEW_COL FROM " + viewName);
-                tenantConn.createStatement().execute("SELECT NEW_COL FROM " + baseTable);
-            }
-        }
-    }
-    
-    @Test
-    public void testDropColumnOnTableWithViewsNotAllowed() throws Exception {
-        String baseTable = "testDropColumnOnTableWithViewsNotAllowed";
-        String viewName = baseTable + "_view";
-        try (Connection conn = DriverManager.getConnection(getUrl())) {
-            String tableDDL = "CREATE TABLE " + baseTable + " (PK1 VARCHAR NOT NULL PRIMARY KEY, V1 VARCHAR, V2 VARCHAR)";
-            conn.createStatement().execute(tableDDL);
-            
-            String viewDDL = "CREATE VIEW " + viewName + " AS SELECT * FROM " + baseTable;
-            conn.createStatement().execute(viewDDL);
-            
-            String dropColumn = "ALTER TABLE " + baseTable + " DROP COLUMN V2";
-            try {
-                conn.createStatement().execute(dropColumn);
-                fail("Dropping column on a base table that has views is not allowed");
-            } catch (SQLException e) {  
-                assertEquals(CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
-            }
-        }
-    }
-    
-    @Test
-    public void testAlteringViewThatHasChildViews() throws Exception {
-        String baseTable = "testAlteringViewThatHasChildViews";
-        String childView = "childView";
-        String grandChildView = "grandChildView";
-        try (Connection conn = DriverManager.getConnection(getUrl())) {
-            String baseTableDDL =
-                    "CREATE TABLE " +  baseTable + " (TENANT_ID VARCHAR NOT NULL, PK2 VARCHAR NOT NULL, V1 VARCHAR, V2 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, PK2))";
-            conn.createStatement().execute(baseTableDDL);
-
-            String childViewDDL = "CREATE VIEW " + childView + " AS SELECT * FROM " + baseTable;
-            conn.createStatement().execute(childViewDDL);
-
-            String addColumnToChildViewDDL =
-                    "ALTER VIEW " + childView + " ADD CHILD_VIEW_COL VARCHAR";
-            conn.createStatement().execute(addColumnToChildViewDDL);
-
-            String grandChildViewDDL =
-                    "CREATE VIEW " + grandChildView + " AS SELECT * FROM " + childView;
-            conn.createStatement().execute(grandChildViewDDL);
-
-            // dropping base table column from child view should succeed
-            String dropColumnFromChildView = "ALTER VIEW " + childView + " DROP COLUMN V2";
-            conn.createStatement().execute(dropColumnFromChildView);
-
-            // dropping view specific column from child view should succeed
-            dropColumnFromChildView = "ALTER VIEW " + childView + " DROP COLUMN CHILD_VIEW_COL";
-            conn.createStatement().execute(dropColumnFromChildView);
-            
-            // Adding column to view that has child views is allowed
-            String addColumnToChildView = "ALTER VIEW " + childView + " ADD V5 VARCHAR";
-            conn.createStatement().execute(addColumnToChildView);
-            // V5 column should be visible now for childView
-            conn.createStatement().execute("SELECT V5 FROM " + childView);    
-            
-            // However, column V5 shouldn't have propagated to grandChildView. Not till PHOENIX-2054 is fixed.
-            try {
-                conn.createStatement().execute("SELECT V5 FROM " + grandChildView);
-            } catch (SQLException e) {
-                assertEquals(SQLExceptionCode.COLUMN_NOT_FOUND.getErrorCode(), e.getErrorCode());
-            }
-
-            // dropping column from the grand child view, however, should work.
-            String dropColumnFromGrandChildView =
-                    "ALTER VIEW " + grandChildView + " DROP COLUMN CHILD_VIEW_COL";
-            conn.createStatement().execute(dropColumnFromGrandChildView);
-
-            // similarly, dropping column inherited from the base table should work.
-            dropColumnFromGrandChildView = "ALTER VIEW " + grandChildView + " DROP COLUMN V2";
-            conn.createStatement().execute(dropColumnFromGrandChildView);
-        }
-    }
-    
-    @Test
-    public void testDivergedViewsStayDiverged() throws Exception {
-        String baseTable = "testDivergedViewsStayDiverged";
-        String view1 = baseTable + "_view1";
-        String view2 = baseTable + "_view2";
-        try (Connection conn = DriverManager.getConnection(getUrl())) {
-            String tableDDL = "CREATE TABLE " + baseTable + " (PK1 VARCHAR NOT NULL PRIMARY KEY, V1 VARCHAR, V2 VARCHAR)";
-            conn.createStatement().execute(tableDDL);
-            
-            String viewDDL = "CREATE VIEW " + view1 + " AS SELECT * FROM " + baseTable;
-            conn.createStatement().execute(viewDDL);
-            
-            viewDDL = "CREATE VIEW " + view2 + " AS SELECT * FROM " + baseTable;
-            conn.createStatement().execute(viewDDL);
-            
-            // Drop the column inherited from base table to make it diverged
-            String dropColumn = "ALTER VIEW " + view1 + " DROP COLUMN V2";
-            conn.createStatement().execute(dropColumn);
-            
-            String alterBaseTable = "ALTER TABLE " + baseTable + " ADD V3 VARCHAR";
-            conn.createStatement().execute(alterBaseTable);
-	        
-            // Column V3 shouldn't have propagated to the diverged view.
-            String sql = "SELECT V3 FROM " + view1;
-            try {
-                conn.createStatement().execute(sql);
-            } catch (SQLException e) {
-                assertEquals(SQLExceptionCode.COLUMN_NOT_FOUND.getErrorCode(), e.getErrorCode());
-            }
-            
-            // However, column V3 should have propagated to the non-diverged view.
-            sql = "SELECT V3 FROM " + view2;
-            conn.createStatement().execute(sql);
-        } 
-    }
-    
-    @Test
-    public void testAddingColumnToBaseTablePropagatesToEntireViewHierarchy() throws Exception {
-        String baseTable = "testViewHierarchy";
-        String view1 = "view1";
-        String view2 = "view2";
-        String view3 = "view3";
-        String view4 = "view4";
-        /*                                     baseTable
-                                 /                  |               \ 
-                         view1(tenant1)    view3(tenant2)          view4(global)
-                          /
-                        view2(tenant1)  
-        */
-        try (Connection conn = DriverManager.getConnection(getUrl())) {
-            String baseTableDDL = "CREATE TABLE " + baseTable + " (TENANT_ID VARCHAR NOT NULL, PK1 VARCHAR NOT NULL, V1 VARCHAR, V2 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, PK1)) MULTI_TENANT = true ";
-            conn.createStatement().execute(baseTableDDL);
-            
-            try (Connection tenant1Conn = getTenantConnection("tenant1")) {
-                String view1DDL = "CREATE VIEW " + view1 + " AS SELECT * FROM " + baseTable;
-                tenant1Conn.createStatement().execute(view1DDL);
-                
-                String view2DDL = "CREATE VIEW " + view2 + " AS SELECT * FROM " + view1;
-                tenant1Conn.createStatement().execute(view2DDL);
-            }
-            
-            try (Connection tenant2Conn = getTenantConnection("tenant2")) {
-                String view3DDL = "CREATE VIEW " + view3 + " AS SELECT * FROM " + baseTable;
-                tenant2Conn.createStatement().execute(view3DDL);
-            }
-            
-            String view4DDL = "CREATE VIEW " + view4 + " AS SELECT * FROM " + baseTable;
-            conn.createStatement().execute(view4DDL);
-            
-            String alterBaseTable = "ALTER TABLE " + baseTable + " ADD V3 VARCHAR";
-            conn.createStatement().execute(alterBaseTable);
-            
-            // verify that the column is visible to view4
-            conn.createStatement().execute("SELECT V3 FROM " + view4);
-            
-            // verify that the column is visible to view1 and view2
-            try (Connection tenant1Conn = getTenantConnection("tenant1")) {
-                tenant1Conn.createStatement().execute("SELECT V3 from " + view1);
-                tenant1Conn.createStatement().execute("SELECT V3 from " + view2);
-            }
-            
-            // verify that the column is visible to view3
-            try (Connection tenant2Conn = getTenantConnection("tenant2")) {
-                tenant2Conn.createStatement().execute("SELECT V3 from " + view3);
-            }
-            
-        }
-           
-    }
-    
-    @Test
-    public void testChangingPKOfBaseTableChangesPKForAllViews() throws Exception {
-        String baseTable = "testChangePKOfBaseTable";
-        String view1 = "view1";
-        String view2 = "view2";
-        String view3 = "view3";
-        String view4 = "view4";
-        /*                                     baseTable
-                                 /                  |               \ 
-                         view1(tenant1)    view3(tenant2)          view4(global)
-                          /
-                        view2(tenant1)  
-         */
-        Connection tenant1Conn = null, tenant2Conn = null;
-        try (Connection globalConn = DriverManager.getConnection(getUrl())) {
-            String baseTableDDL = "CREATE TABLE "
-                    + baseTable
-                    + " (TENANT_ID VARCHAR NOT NULL, PK1 VARCHAR NOT NULL, V1 VARCHAR, V2 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, PK1)) MULTI_TENANT = true ";
-            globalConn.createStatement().execute(baseTableDDL);
-
-            tenant1Conn = getTenantConnection("tenant1");
-            String view1DDL = "CREATE VIEW " + view1 + " AS SELECT * FROM " + baseTable;
-            tenant1Conn.createStatement().execute(view1DDL);
-
-            String view2DDL = "CREATE VIEW " + view2 + " AS SELECT * FROM " + view1;
-            tenant1Conn.createStatement().execute(view2DDL);
-
-            tenant2Conn = getTenantConnection("tenant2");
-            String view3DDL = "CREATE VIEW " + view3 + " AS SELECT * FROM " + baseTable;
-            tenant2Conn.createStatement().execute(view3DDL);
-
-            String view4DDL = "CREATE VIEW " + view4 + " AS SELECT * FROM " + baseTable;
-            globalConn.createStatement().execute(view4DDL);
-
-            String alterBaseTable = "ALTER TABLE " + baseTable + " ADD NEW_PK varchar primary key ";
-            globalConn.createStatement().execute(alterBaseTable);
-            
-            // verify that the new column new_pk is now part of the primary key for the entire hierarchy
-            
-            globalConn.createStatement().execute("SELECT * FROM " + baseTable);
-            assertTrue(checkColumnPartOfPk(globalConn.unwrap(PhoenixConnection.class), "NEW_PK", baseTable));
-            
-            tenant1Conn.createStatement().execute("SELECT * FROM " + view1);
-            assertTrue(checkColumnPartOfPk(tenant1Conn.unwrap(PhoenixConnection.class), "NEW_PK", view1));
-            
-            tenant1Conn.createStatement().execute("SELECT * FROM " + view2);
-            assertTrue(checkColumnPartOfPk(tenant1Conn.unwrap(PhoenixConnection.class), "NEW_PK", view2));
-            
-            tenant2Conn.createStatement().execute("SELECT * FROM " + view3);
-            assertTrue(checkColumnPartOfPk(tenant2Conn.unwrap(PhoenixConnection.class), "NEW_PK", view3));
-            
-            globalConn.createStatement().execute("SELECT * FROM " + view4);
-            assertTrue(checkColumnPartOfPk(globalConn.unwrap(PhoenixConnection.class), "NEW_PK", view4));
-
-        } finally {
-            if (tenant1Conn != null) {
-                try {
-                    tenant1Conn.close();
-                } catch (Throwable ignore) {}
-            }
-            if (tenant2Conn != null) {
-                try {
-                    tenant2Conn.close();
-                } catch (Throwable ignore) {}
-            }
-        }
-
-    }
-    
-    private boolean checkColumnPartOfPk(PhoenixConnection conn, String columnName, String tableName) throws SQLException {
-        String normalizedTableName = SchemaUtil.normalizeIdentifier(tableName);
-        PTable table = conn.getMetaDataCache().getTable(new PTableKey(conn.getTenantId(), normalizedTableName));
-        List<PColumn> pkCols = table.getPKColumns();
-        String normalizedColumnName = SchemaUtil.normalizeIdentifier(columnName);
-        for (PColumn pkCol : pkCols) {
-            if (pkCol.getName().getString().equals(normalizedColumnName)) {
-                return true;
-            }
-        }
-        return false;
-    }
-    
-    private int getIndexOfPkColumn(PhoenixConnection conn, String columnName, String tableName) throws SQLException {
-        String normalizedTableName = SchemaUtil.normalizeIdentifier(tableName);
-        PTable table = conn.getMetaDataCache().getTable(new PTableKey(conn.getTenantId(), normalizedTableName));
-        List<PColumn> pkCols = table.getPKColumns();
-        String normalizedColumnName = SchemaUtil.normalizeIdentifier(columnName);
-        int i = 0;
-        for (PColumn pkCol : pkCols) {
-            if (pkCol.getName().getString().equals(normalizedColumnName)) {
-                return i;
-            }
-            i++;
-        }
-        return -1;
-    }
-    
-    private Connection getTenantConnection(String tenantId) throws Exception {
-        Properties tenantProps = new Properties();
-        tenantProps.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, tenantId);
-        return DriverManager.getConnection(getUrl(), tenantProps);
-    }
-    
-    @Test
-    public void testAddPKColumnToBaseTableWhoseViewsHaveIndices() throws Exception {
-        String baseTable = "testAddPKColumnToBaseTableWhoseViewsHaveIndices";
-        String view1 = "view1";
-        String view2 = "view2";
-        String view3 = "view3";
-        String tenant1 = "tenant1";
-        String tenant2 = "tenant2";
-        String view2Index = view2 + "_idx";
-        String view3Index = view3 + "_idx";
-        /*                          baseTable(mutli-tenant)
-                                 /                           \                
-                         view1(tenant1)                  view3(tenant2, index) 
-                          /
-                        view2(tenant1, index)  
-         */
-        try (Connection globalConn = DriverManager.getConnection(getUrl())) {
-            // make sure that the tables are empty, but reachable
-            globalConn
-            .createStatement()
-            .execute(
-                    "CREATE TABLE "
-                            + baseTable
-                            + " (TENANT_ID VARCHAR NOT NULL, K1 varchar not null, V1 VARCHAR, V2 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, K1)) MULTI_TENANT = true ");
-
-        }
-        try (Connection tenantConn = getTenantConnection(tenant1)) {
-            // create tenant specific view for tenant1 - view1
-            tenantConn.createStatement().execute("CREATE VIEW " + view1 + " AS SELECT * FROM " + baseTable);
-            PhoenixConnection phxConn = tenantConn.unwrap(PhoenixConnection.class);
-            assertEquals(0, getTableSequenceNumber(phxConn, view1));
-            assertEquals(2, getMaxKeySequenceNumber(phxConn, view1));
-
-            // create a view - view2 on view - view1
-            tenantConn.createStatement().execute("CREATE VIEW " + view2 + " AS SELECT * FROM " + view1);
-            assertEquals(0, getTableSequenceNumber(phxConn, view2));
-            assertEquals(2, getMaxKeySequenceNumber(phxConn, view2));
-
-
-            // create an index on view2
-            tenantConn.createStatement().execute("CREATE INDEX " + view2Index + " ON " + view2 + " (v1) include (v2)");
-            assertEquals(0, getTableSequenceNumber(phxConn, view2Index));
-            assertEquals(4, getMaxKeySequenceNumber(phxConn, view2Index));
-        }
-        try (Connection tenantConn = getTenantConnection(tenant2)) {
-            // create tenant specific view for tenant2 - view3
-            tenantConn.createStatement().execute("CREATE VIEW " + view3 + " AS SELECT * FROM " + baseTable);
-            PhoenixConnection phxConn = tenantConn.unwrap(PhoenixConnection.class);
-            assertEquals(0, getTableSequenceNumber(phxConn, view3));
-            assertEquals(2, getMaxKeySequenceNumber(phxConn, view3));
-
-
-            // create an index on view3
-            tenantConn.createStatement().execute("CREATE INDEX " + view3Index + " ON " + view3 + " (v1) include (v2)");
-            assertEquals(0, getTableSequenceNumber(phxConn, view3Index));
-            assertEquals(4, getMaxKeySequenceNumber(phxConn, view3Index));
-
-
-        }
-
-        // alter the base table by adding 1 non-pk and 2 pk columns
-        try (Connection globalConn = DriverManager.getConnection(getUrl())) {
-            globalConn.createStatement().execute("ALTER TABLE " + baseTable + " ADD v3 VARCHAR, k2 VARCHAR PRIMARY KEY, k3 VARCHAR PRIMARY KEY");
-            assertEquals(4, getMaxKeySequenceNumber(globalConn.unwrap(PhoenixConnection.class), baseTable));
-
-            // Upsert records in the base table
-            String upsert = "UPSERT INTO " + baseTable + " (TENANT_ID, K1, K2, K3, V1, V2, V3) VALUES (?, ?, ?, ?, ?, ?, ?)";
-            PreparedStatement stmt = globalConn.prepareStatement(upsert);
-            stmt.setString(1, tenant1);
-            stmt.setString(2, "K1");
-            stmt.setString(3, "K2");
-            stmt.setString(4, "K3");
-            stmt.setString(5, "V1");
-            stmt.setString(6, "V2");
-            stmt.setString(7, "V3");
-            stmt.executeUpdate();
-            stmt.setString(1, tenant2);
-            stmt.setString(2, "K11");
-            stmt.setString(3, "K22");
-            stmt.setString(4, "K33");
-            stmt.setString(5, "V11");
-            stmt.setString(6, "V22");
-            stmt.setString(7, "V33");
-            stmt.executeUpdate();
-            globalConn.commit();
-        }
-
-        // Verify now that the sequence number of data table, indexes and views have changed.
-        // Also verify that the newly added pk columns show up as pk columns of data table, indexes and views.
-        try (Connection tenantConn = getTenantConnection(tenant1)) {
-
-            ResultSet rs = tenantConn.createStatement().executeQuery("SELECT K2, K3, V3 FROM " + view1);
-            PhoenixConnection phxConn = tenantConn.unwrap(PhoenixConnection.class);
-            assertEquals(2, getIndexOfPkColumn(phxConn, "k2", view1));
-            assertEquals(3, getIndexOfPkColumn(phxConn, "k3", view1));
-            assertEquals(1, getTableSequenceNumber(phxConn, view1));
-            assertEquals(4, getMaxKeySequenceNumber(phxConn, view1));
-            verifyNewColumns(rs, "K2", "K3", "V3");
-
-
-            rs = tenantConn.createStatement().executeQuery("SELECT K2, K3, V3 FROM " + view2);
-            assertEquals(2, getIndexOfPkColumn(phxConn, "k2", view2));
-            assertEquals(3, getIndexOfPkColumn(phxConn, "k3", view2));
-            assertEquals(1, getTableSequenceNumber(phxConn, view2));
-            assertEquals(4, getMaxKeySequenceNumber(phxConn, view2));
-            verifyNewColumns(rs, "K2", "K3", "V3");
-
-            assertEquals(4, getIndexOfPkColumn(phxConn, IndexUtil.getIndexColumnName(null, "k2"), view2Index));
-            assertEquals(5, getIndexOfPkColumn(phxConn, IndexUtil.getIndexColumnName(null, "k3"), view2Index));
-            assertEquals(1, getTableSequenceNumber(phxConn, view2Index));
-            assertEquals(6, getMaxKeySequenceNumber(phxConn, view2Index));
-        }
-        try (Connection tenantConn = getTenantConnection(tenant2)) {
-            ResultSet rs = tenantConn.createStatement().executeQuery("SELECT K2, K3, V3 FROM " + view3);
-            PhoenixConnection phxConn = tenantConn.unwrap(PhoenixConnection.class);
-            assertEquals(2, getIndexOfPkColumn(phxConn, "k2", view3));
-            assertEquals(3, getIndexOfPkColumn(phxConn, "k3", view3));
-            assertEquals(1, getTableSequenceNumber(phxConn, view3));
-            verifyNewColumns(rs, "K22", "K33", "V33");
-
-            assertEquals(4, getIndexOfPkColumn(phxConn, IndexUtil.getIndexColumnName(null, "k2"), view3Index));
-            assertEquals(5, getIndexOfPkColumn(phxConn, IndexUtil.getIndexColumnName(null, "k3"), view3Index));
-            assertEquals(1, getTableSequenceNumber(phxConn, view3Index));
-            assertEquals(6, getMaxKeySequenceNumber(phxConn, view3Index));
-        }
-        // Verify that the index is actually being used when using newly added pk col
-        try (Connection tenantConn = getTenantConnection(tenant1)) {
-            String upsert = "UPSERT INTO " + view2 + " (K1, K2, K3, V1, V2, V3) VALUES ('key1', 'key2', 'key3', 'value1', 'value2', 'value3')";
-            tenantConn.createStatement().executeUpdate(upsert);
-            tenantConn.commit();
-            Statement stmt = tenantConn.createStatement();
-            String sql = "SELECT V2 FROM " + view2 + " WHERE V1 = 'value1' AND K3 = 'key3'";
-            QueryPlan plan = stmt.unwrap(PhoenixStatement.class).optimizeQuery(sql);
-            assertTrue(plan.getTableRef().getTable().getName().getString().equals(SchemaUtil.normalizeIdentifier(view2Index)));
-            ResultSet rs = tenantConn.createStatement().executeQuery(sql);
-            verifyNewColumns(rs, "value2");
-        }
-
-    }
-    
-    private static long getTableSequenceNumber(PhoenixConnection conn, String tableName) throws SQLException {
-        PTable table = conn.getMetaDataCache().getTable(new PTableKey(conn.getTenantId(), SchemaUtil.normalizeIdentifier(tableName)));
-        return table.getSequenceNumber();
-    }
-    
-    private static short getMaxKeySequenceNumber(PhoenixConnection conn, String tableName) throws SQLException {
-        PTable table = conn.getMetaDataCache().getTable(new PTableKey(conn.getTenantId(), SchemaUtil.normalizeIdentifier(tableName)));
-        return SchemaUtil.getMaxKeySeq(table);
-    }
-    
-    private static void verifyNewColumns(ResultSet rs, String ... values) throws SQLException {
-        assertTrue(rs.next());
-        int i = 1;
-        for (String value : values) {
-            assertEquals(value, rs.getString(i++));
-        }
-        assertFalse(rs.next());
-    }
-    
 }
+ 
\ No newline at end of file


[17/40] phoenix git commit: PHOENIX 2132 Minor addendum to fix RAT warning

Posted by ma...@apache.org.
PHOENIX 2132 Minor addendum to fix RAT warning


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/ce898055
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/ce898055
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/ce898055

Branch: refs/heads/calcite
Commit: ce89805535664a63b0df6c633d2ad0def5679250
Parents: c65ef90
Author: Mujtaba <mu...@apache.org>
Authored: Fri Jul 24 11:55:45 2015 -0700
Committer: Mujtaba <mu...@apache.org>
Committed: Fri Jul 24 11:55:45 2015 -0700

----------------------------------------------------------------------
 phoenix-pherf/pom.xml | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/ce898055/phoenix-pherf/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-pherf/pom.xml b/phoenix-pherf/pom.xml
index e08670c..b734e4d 100644
--- a/phoenix-pherf/pom.xml
+++ b/phoenix-pherf/pom.xml
@@ -195,7 +195,8 @@
 				<artifactId>apache-rat-plugin</artifactId>
 				<configuration>
 					<excludes>
-						<exclude>RESULTS/**</exclude>
+						<exclude>*/RESULTS/**</exclude>
+						<exclude>README.md</exclude>
 					</excludes>
 				</configuration>
 			</plugin>


[24/40] phoenix git commit: PHOENIX-2145 Pherf - Make update stats optional and fix threads not exiting after performance run

Posted by ma...@apache.org.
PHOENIX-2145 Pherf - Make update stats optional and fix threads not exiting after performance run


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/d41a0fcb
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/d41a0fcb
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/d41a0fcb

Branch: refs/heads/calcite
Commit: d41a0fcbd75456bc68eaa673361290504abd9895
Parents: e4ed2d9
Author: Mujtaba <mu...@apache.org>
Authored: Tue Aug 4 15:47:44 2015 -0700
Committer: Mujtaba <mu...@apache.org>
Committed: Tue Aug 4 15:47:44 2015 -0700

----------------------------------------------------------------------
 phoenix-pherf/pom.xml                           |  3 --
 .../org/apache/phoenix/pherf/DataIngestIT.java  |  4 +-
 .../src/main/assembly/components-minimal.xml    |  2 +-
 .../java/org/apache/phoenix/pherf/Pherf.java    | 23 +++++------
 .../apache/phoenix/pherf/PherfConstants.java    |  5 +++
 .../apache/phoenix/pherf/util/PhoenixUtil.java  | 11 +++++
 .../phoenix/pherf/workload/QueryExecutor.java   |  3 +-
 .../phoenix/pherf/workload/WriteWorkload.java   | 43 ++++++++++----------
 .../org/apache/phoenix/pherf/PherfTest.java     |  2 +-
 9 files changed, 55 insertions(+), 41 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/d41a0fcb/phoenix-pherf/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-pherf/pom.xml b/phoenix-pherf/pom.xml
index 66b949b..b548c04 100644
--- a/phoenix-pherf/pom.xml
+++ b/phoenix-pherf/pom.xml
@@ -108,9 +108,6 @@
 			</resource>
 			<resource>
 				<directory>config</directory>
-				<includes>
-					<include>**/*.properties</include>
-				</includes>
 			</resource>
 		</resources>
 		<testResources>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/d41a0fcb/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/DataIngestIT.java
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/DataIngestIT.java b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/DataIngestIT.java
index 8a340b3..1defbb1 100644
--- a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/DataIngestIT.java
+++ b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/DataIngestIT.java
@@ -20,6 +20,8 @@ package org.apache.phoenix.pherf;
 
 import com.jcabi.jdbc.JdbcSession;
 import com.jcabi.jdbc.Outcome;
+
+import org.apache.phoenix.pherf.PherfConstants.GeneratePhoenixStats;
 import org.apache.phoenix.pherf.configuration.Column;
 import org.apache.phoenix.pherf.configuration.DataModel;
 import org.apache.phoenix.pherf.configuration.DataTypeMapping;
@@ -66,7 +68,7 @@ public class DataIngestIT extends ResultBaseTestIT {
                             scenario.getTableNameWithoutSchemaName(), util.getConnection());
             assertTrue("Could not get phoenix columns.", columnListFromPhoenix.size() > 0);
 
-            WriteWorkload loader = new WriteWorkload(util, parser, scenario);
+            WriteWorkload loader = new WriteWorkload(util, parser, scenario, GeneratePhoenixStats.NO);
             WorkloadExecutor executor = new WorkloadExecutor();
             executor.add(loader);
             executor.get();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/d41a0fcb/phoenix-pherf/src/main/assembly/components-minimal.xml
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/assembly/components-minimal.xml b/phoenix-pherf/src/main/assembly/components-minimal.xml
index 38c6929..9c9b9a1 100644
--- a/phoenix-pherf/src/main/assembly/components-minimal.xml
+++ b/phoenix-pherf/src/main/assembly/components-minimal.xml
@@ -23,7 +23,7 @@
       <outputDirectory>/</outputDirectory>
       <includes>
         <include>org.apache.phoenix:phoenix-pherf</include>
-        <include>org.jfree:jfreechart</include>
+        <include>org.jfree:*</include>
         <include>com.googlecode.java-diff-utils:diffutils</include>
         <include>org.apache.commons:commons-lang3</include>
         <include>org.apache.commons:commons-math3</include>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/d41a0fcb/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/Pherf.java
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/Pherf.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/Pherf.java
index 5a9f45f..0421b6f 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/Pherf.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/Pherf.java
@@ -19,6 +19,7 @@
 package org.apache.phoenix.pherf;
 
 import org.apache.commons.cli.*;
+import org.apache.phoenix.pherf.PherfConstants.GeneratePhoenixStats;
 import org.apache.phoenix.pherf.configuration.XMLConfigParser;
 import org.apache.phoenix.pherf.jmx.MonitorManager;
 import org.apache.phoenix.pherf.schema.SchemaReader;
@@ -73,6 +74,8 @@ public class Pherf {
                         + "See pherf.default.dataloader.threadpool in Pherf.properties.");
         options.addOption("h", "help", false, "Get help on using this utility.");
         options.addOption("d", "debug", false, "Put tool in debug mode");
+        options.addOption("stats", false,
+                "Update Phoenix Statistics after data is loaded with -l argument");
     }
 
     private final String zookeeper;
@@ -89,6 +92,7 @@ public class Pherf {
     private final int rowCountOverride;
     private final boolean listFiles;
     private final boolean applySchema;
+    private final GeneratePhoenixStats generateStatistics;
 
     public Pherf(String[] args) throws Exception {
         CommandLineParser parser = new PosixParser();
@@ -126,6 +130,7 @@ public class Pherf {
                 command.hasOption("scenarioFile") ? command.getOptionValue("scenarioFile") : null;
         schemaFile = command.hasOption("schemaFile") ? command.getOptionValue("schemaFile") : null;
         rowCountOverride = Integer.parseInt(command.getOptionValue("rowCountOverride", "0"));
+        generateStatistics = command.hasOption("stats") ? GeneratePhoenixStats.YES : GeneratePhoenixStats.NO;
         String
                 writerThreadPoolSize =
                 command.getOptionValue("writerThreadSize",
@@ -204,23 +209,11 @@ public class Pherf {
             // Schema and Data Load
             if (preLoadData) {
                 logger.info("\nStarting Data Load...");
-                WriteWorkload workload = new WriteWorkload(parser);
+                WriteWorkload workload = new WriteWorkload(parser, generateStatistics);
                 workloadExecutor.add(workload);
 
                 // Wait for dataLoad to complete
                 workloadExecutor.get(workload);
-
-                logger.info("\nGenerate query gold files after data load");
-                QueryExecutor
-                        goldFileGenerator =
-                        new QueryExecutor(parser, phoenixUtil, workloadExecutor.getPool(),
-                                parser.getDataModels(), queryHint, true,
-                                PherfConstants.RunMode.FUNCTIONAL);
-                workloadExecutor
-                        .add(goldFileGenerator);
-
-                // Wait for dataLoad to complete
-                workloadExecutor.get(goldFileGenerator);
             } else {
                 logger.info(
                         "\nSKIPPED: Data Load and schema creation as -l argument not specified");
@@ -254,6 +247,10 @@ public class Pherf {
             if (workloadExecutor != null) {
                 logger.info("Run completed. Shutting down thread pool.");
                 workloadExecutor.shutdown();
+                if (preLoadData) {
+                	System.exit(0);
+                }
+                
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/d41a0fcb/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/PherfConstants.java
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/PherfConstants.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/PherfConstants.java
index e060e53..12580d4 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/PherfConstants.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/PherfConstants.java
@@ -62,6 +62,11 @@ public class PherfConstants {
     public static final int MONITOR_FREQUENCY = 5000;
     public static final String MONITOR_FILE_NAME = "STATS_MONITOR";
 
+    public static enum GeneratePhoenixStats {
+        YES,
+        NO
+    }
+    
     public static enum RunMode {
         PERFORMANCE,
         FUNCTIONAL

http://git-wip-us.apache.org/repos/asf/phoenix/blob/d41a0fcb/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/util/PhoenixUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/util/PhoenixUtil.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/util/PhoenixUtil.java
index 5f7d637..5b223b1 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/util/PhoenixUtil.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/util/PhoenixUtil.java
@@ -255,4 +255,15 @@ public class PhoenixUtil {
 	public static void setRowCountOverride(int rowCountOverride) {
 		PhoenixUtil.rowCountOverride = rowCountOverride;
 	}
+	
+    /**
+     * Update Phoenix table stats
+     *
+     * @param tableName
+     * @throws Exception
+     */
+    public void updatePhoenixStats(String tableName) throws Exception {
+        logger.info("Updating stats for " + tableName);
+        executeStatement("UPDATE STATISTICS " + tableName);
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/d41a0fcb/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/QueryExecutor.java
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/QueryExecutor.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/QueryExecutor.java
index 624188c..4ab76c8 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/QueryExecutor.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/QueryExecutor.java
@@ -20,6 +20,7 @@ package org.apache.phoenix.pherf.workload;
 
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.phoenix.pherf.PherfConstants.GeneratePhoenixStats;
 import org.apache.phoenix.pherf.PherfConstants.RunMode;
 import org.apache.phoenix.pherf.configuration.*;
 import org.apache.phoenix.pherf.result.*;
@@ -142,7 +143,7 @@ public class QueryExecutor implements Workload {
                             for (int i = 0; i < writerThreadCount; i++) {
                                 logger.debug("Inserting write workload ( " + i + " ) of ( "
                                         + writerThreadCount + " )");
-                                Workload writes = new WriteWorkload(PhoenixUtil.create(), parser);
+                                Workload writes = new WriteWorkload(PhoenixUtil.create(), parser, GeneratePhoenixStats.NO);
                                 pool.submit(writes.execute());
                             }
                         }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/d41a0fcb/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/WriteWorkload.java
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/WriteWorkload.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/WriteWorkload.java
index 305521b..b6686c6 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/WriteWorkload.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/WriteWorkload.java
@@ -19,6 +19,7 @@
 package org.apache.phoenix.pherf.workload;
 
 import org.apache.phoenix.pherf.PherfConstants;
+import org.apache.phoenix.pherf.PherfConstants.GeneratePhoenixStats;
 import org.apache.phoenix.pherf.configuration.Column;
 import org.apache.phoenix.pherf.configuration.Scenario;
 import org.apache.phoenix.pherf.configuration.WriteParams;
@@ -58,19 +59,24 @@ public class WriteWorkload implements Workload {
 
     private final int threadPoolSize;
     private final int batchSize;
+    private final GeneratePhoenixStats generateStatistics;
 
     public WriteWorkload(XMLConfigParser parser) throws Exception {
-        this(PhoenixUtil.create(), parser);
+        this(PhoenixUtil.create(), parser, GeneratePhoenixStats.NO);
+    }
+    
+    public WriteWorkload(XMLConfigParser parser, GeneratePhoenixStats generateStatistics) throws Exception {
+        this(PhoenixUtil.create(), parser, generateStatistics);
     }
 
-    public WriteWorkload(PhoenixUtil util, XMLConfigParser parser) throws Exception {
-        this(util, parser, null);
+    public WriteWorkload(PhoenixUtil util, XMLConfigParser parser, GeneratePhoenixStats generateStatistics) throws Exception {
+        this(util, parser, null, generateStatistics);
     }
 
-    public WriteWorkload(PhoenixUtil phoenixUtil, XMLConfigParser parser, Scenario scenario)
+    public WriteWorkload(PhoenixUtil phoenixUtil, XMLConfigParser parser, Scenario scenario, GeneratePhoenixStats generateStatistics)
             throws Exception {
         this(phoenixUtil, PherfConstants.create().getProperties(PherfConstants.PHERF_PROPERTIES),
-                parser, scenario);
+                parser, scenario, generateStatistics);
     }
 
     /**
@@ -87,11 +93,12 @@ public class WriteWorkload implements Workload {
      * @throws Exception
      */
     public WriteWorkload(PhoenixUtil phoenixUtil, Properties properties, XMLConfigParser parser,
-            Scenario scenario) throws Exception {
+            Scenario scenario, GeneratePhoenixStats generateStatistics) throws Exception {
         this.pUtil = phoenixUtil;
         this.parser = parser;
         this.rulesApplier = new RulesApplier(parser);
         this.resultUtil = new ResultUtil();
+        this.generateStatistics = generateStatistics;
 
         // Overwrite defaults properties with those given in the configuration. This indicates the
         // scenario is a R/W mixed workload.
@@ -156,9 +163,15 @@ public class WriteWorkload implements Workload {
         List<Future> writeBatches = getBatches(dataLoadThreadTime, scenario);
 
         waitForBatches(dataLoadTimeSummary, scenario, start, writeBatches);
-
-        // always update stats for Phoenix base tables
-        updatePhoenixStats(scenario.getTableName());
+        
+        // Update Phoenix Statistics
+        if (this.generateStatistics == GeneratePhoenixStats.YES) {
+        	logger.info("Updating Phoenix table statistics...");
+        	pUtil.updatePhoenixStats(scenario.getTableName());
+        	logger.info("Stats update done!");
+        } else {
+        	logger.info("Phoenix table stats update not requested.");
+        }
     }
 
     private List<Future> getBatches(DataLoadThreadTime dataLoadThreadTime, Scenario scenario)
@@ -208,18 +221,6 @@ public class WriteWorkload implements Workload {
                 .add(scenario.getTableName(), sumRows, (int) (System.currentTimeMillis() - start));
     }
 
-    /**
-     * TODO Move this method to PhoenixUtil
-     * Update Phoenix table stats
-     *
-     * @param tableName
-     * @throws Exception
-     */
-    public void updatePhoenixStats(String tableName) throws Exception {
-        logger.info("Updating stats for " + tableName);
-        pUtil.executeStatement("UPDATE STATISTICS " + tableName);
-    }
-
     public Future<Info> upsertData(final Scenario scenario, final List<Column> columns,
             final String tableName, final int rowCount,
             final DataLoadThreadTime dataLoadThreadTime) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/d41a0fcb/phoenix-pherf/src/test/java/org/apache/phoenix/pherf/PherfTest.java
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/test/java/org/apache/phoenix/pherf/PherfTest.java b/phoenix-pherf/src/test/java/org/apache/phoenix/pherf/PherfTest.java
index 94c8171..731a57a 100644
--- a/phoenix-pherf/src/test/java/org/apache/phoenix/pherf/PherfTest.java
+++ b/phoenix-pherf/src/test/java/org/apache/phoenix/pherf/PherfTest.java
@@ -34,7 +34,7 @@ public class PherfTest {
 
     @Test
     public void testUnknownOption() {
-        String[] args = {"-drop", "all", "-l", "-q", "-m","-bsOption"};
+        String[] args = {"-drop", "all", "-q", "-m","-bsOption"};
 
         // Makes sure that System.exit(1) is called. Release is a required param.
         exit.expectSystemExitWithStatus(1);


[07/40] phoenix git commit: PHOENIX-2120 Padding character is not inverted as required for DESC CHAR columns

Posted by ma...@apache.org.
PHOENIX-2120 Padding character is not inverted as required for DESC CHAR columns


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/498cc552
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/498cc552
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/498cc552

Branch: refs/heads/calcite
Commit: 498cc5524ff73c3947160ddfc4241f759c7044f2
Parents: 8c2b5a6
Author: James Taylor <jt...@salesforce.com>
Authored: Wed Jul 22 09:18:00 2015 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Wed Jul 22 09:32:25 2015 -0700

----------------------------------------------------------------------
 .../org/apache/phoenix/end2end/BaseQueryIT.java |  10 --
 .../org/apache/phoenix/end2end/InListIT.java    |  53 +++++++++-
 .../apache/phoenix/end2end/RTrimFunctionIT.java |  71 +++++++++++++
 .../org/apache/phoenix/end2end/SortOrderIT.java |  59 +++++++++++
 .../phoenix/compile/ExpressionCompiler.java     |  12 ++-
 .../apache/phoenix/compile/WhereOptimizer.java  | 102 ++-----------------
 .../apache/phoenix/execute/HashJoinPlan.java    |   6 +-
 .../expression/ArrayConstructorExpression.java  |  28 +++--
 .../phoenix/expression/BaseExpression.java      |  43 ++++----
 .../phoenix/expression/CoerceExpression.java    |  39 ++++---
 .../expression/ComparisonExpression.java        |  32 +++---
 .../phoenix/expression/InListExpression.java    |  26 ++++-
 .../phoenix/expression/LiteralExpression.java   |  18 +++-
 .../expression/function/InvertFunction.java     |   6 +-
 .../expression/function/PrefixFunction.java     |  30 ++++--
 .../expression/function/RTrimFunction.java      |  55 ++++++++--
 .../visitor/CloneExpressionVisitor.java         |   2 +-
 .../phoenix/schema/types/PArrayDataType.java    |   4 +-
 .../java/org/apache/phoenix/query/BaseTest.java |   8 ++
 .../java/org/apache/phoenix/util/TestUtil.java  |   4 +-
 20 files changed, 408 insertions(+), 200 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseQueryIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseQueryIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseQueryIT.java
index 5f87e3f..aa5068b 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseQueryIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseQueryIT.java
@@ -23,9 +23,7 @@ import java.io.IOException;
 import java.sql.Connection;
 import java.sql.Date;
 import java.sql.DriverManager;
-import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -120,14 +118,6 @@ public abstract class BaseQueryIT extends BaseClientManagedTimeIT {
         return testCases;
     }
     
-    protected void assertValueEqualsResultSet(ResultSet rs, List<Object> expectedResults) throws SQLException {
-        List<List<Object>> nestedExpectedResults = Lists.newArrayListWithExpectedSize(expectedResults.size());
-        for (Object expectedResult : expectedResults) {
-            nestedExpectedResults.add(Arrays.asList(expectedResult));
-        }
-        assertValuesEqualsResultSet(rs, nestedExpectedResults); 
-    }
-
     protected static boolean compare(CompareOp op, ImmutableBytesWritable lhsOutPtr, ImmutableBytesWritable rhsOutPtr) {
         int compareResult = Bytes.compareTo(lhsOutPtr.get(), lhsOutPtr.getOffset(), lhsOutPtr.getLength(), rhsOutPtr.get(), rhsOutPtr.getOffset(), rhsOutPtr.getLength());
         return ByteUtil.compare(op, compareResult);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/it/java/org/apache/phoenix/end2end/InListIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/InListIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/InListIT.java
index 3fdd906..4aff12b 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/InListIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/InListIT.java
@@ -32,8 +32,9 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Properties;
 
-import org.apache.phoenix.schema.types.PInteger;
+import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PInteger;
 import org.apache.phoenix.schema.types.PLong;
 import org.apache.phoenix.util.PhoenixRuntime;
 import org.apache.phoenix.util.PropertiesUtil;
@@ -428,4 +429,54 @@ public class InListIT extends BaseHBaseManagedTimeIT {
         
         testWithIntegerTypesWithVariedSaltingAndTenancy(DEFAULT_UPSERT_BODIES, whereClause, expecteds);
     }
+    
+    @Test
+    public void testWithFixedLengthDescPK() throws Exception {
+        testWithFixedLengthPK(SortOrder.DESC);
+    }
+    
+    @Test
+    public void testWithFixedLengthAscPK() throws Exception {
+        testWithFixedLengthPK(SortOrder.ASC);        
+    }
+    
+    @Test
+    public void testWithFixedLengthKV() throws Exception {
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        conn.createStatement().execute("CREATE TABLE in_test ( id INTEGER PRIMARY KEY, k CHAR(3))");
+
+        conn.createStatement().execute("upsert into in_test values (1, 'aa')");
+        conn.createStatement().execute("upsert into in_test values (2, 'bb')");
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("select k from in_test WHERE k IN ('aa','bb')");
+        assertTrue(rs.next());
+        assertEquals("aa", rs.getString(1));
+        assertTrue(rs.next());
+        assertEquals("bb", rs.getString(1));
+        assertFalse(rs.next());
+        
+        conn.close();
+    }
+
+    private void testWithFixedLengthPK(SortOrder sortOrder) throws Exception {
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        conn.createStatement().execute("CREATE TABLE in_test ( k CHAR(3) PRIMARY KEY " + (sortOrder == SortOrder.DESC ? "DESC" : "") + ")");
+
+        conn.createStatement().execute("upsert into in_test (k) values ('aa')");
+        conn.createStatement().execute("upsert into in_test (k) values ('bb')");
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("select k from in_test WHERE k IN ('aa','bb')");
+        assertTrue(rs.next());
+        assertEquals(sortOrder == SortOrder.ASC ? "aa" : "bb", rs.getString(1));
+        assertTrue(rs.next());
+        assertEquals(sortOrder == SortOrder.ASC ? "bb" : "aa", rs.getString(1));
+        assertFalse(rs.next());
+        
+        conn.close();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/it/java/org/apache/phoenix/end2end/RTrimFunctionIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/RTrimFunctionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/RTrimFunctionIT.java
new file mode 100644
index 0000000..2caca2b
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/RTrimFunctionIT.java
@@ -0,0 +1,71 @@
+/*
+ * 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.phoenix.end2end;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.QueryUtil;
+import org.junit.Test;
+
+
+public class RTrimFunctionIT extends BaseHBaseManagedTimeIT {
+    
+    @Test
+    public void testWithFixedLengthAscPK() throws Exception {
+        testWithFixedLengthPK(SortOrder.ASC, Arrays.<Object>asList("b", "b ", "b  "));
+    }
+    
+    @Test
+    public void testWithFixedLengthDescPK() throws Exception {
+        testWithFixedLengthPK(SortOrder.DESC, Arrays.<Object>asList("b  ", "b ", "b"));
+    }
+    
+    private void testWithFixedLengthPK(SortOrder sortOrder, List<Object> expectedResults) throws Exception {
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        conn.createStatement().execute("CREATE TABLE rtrim_test ( k VARCHAR PRIMARY KEY " + (sortOrder == SortOrder.DESC ? "DESC" : "") + ")");
+
+        conn.createStatement().execute("upsert into rtrim_test (k) values ('a')");
+        conn.createStatement().execute("upsert into rtrim_test (k) values ('b')");
+        conn.createStatement().execute("upsert into rtrim_test (k) values ('b ')");
+        conn.createStatement().execute("upsert into rtrim_test (k) values ('b  ')");
+        conn.createStatement().execute("upsert into rtrim_test (k) values ('b  a')");
+        conn.createStatement().execute("upsert into rtrim_test (k) values (' b  ')");
+        conn.createStatement().execute("upsert into rtrim_test (k) values ('c')");
+        conn.commit();
+
+        String query = "select k from rtrim_test WHERE rtrim(k)='b'";
+        ResultSet rs = conn.createStatement().executeQuery(query);
+        assertValueEqualsResultSet(rs, expectedResults);
+        
+        rs = conn.createStatement().executeQuery("explain " + query);
+        assertTrue(QueryUtil.getExplainPlan(rs).contains("RANGE SCAN OVER RTRIM_TEST"));
+        
+        conn.close();
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java
index a03f71e..0e8fb4f 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java
@@ -18,6 +18,8 @@
 package org.apache.phoenix.end2end;
 
 import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -171,6 +173,63 @@ public class SortOrderIT extends BaseHBaseManagedTimeIT {
     }    
     
     @Test
+    public void substrFixedLengthDescPK1() throws Exception {
+        String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(3) PRIMARY KEY DESC)";
+        Object[][] insertedRows = new Object[][]{{"a"}, {"ab"}};
+        Object[][] expectedRows = new Object[][]{{"ab"}, {"a"} };
+        runQueryTest(ddl, upsert("oid"), insertedRows, expectedRows, new WhereCondition("SUBSTR(oid, 1, 1)", "=", "'a'"));
+    }
+        
+    @Test
+    public void substrVarLengthDescPK1() throws Exception {
+        String ddl = "CREATE TABLE " + TABLE + " (oid VARCHAR PRIMARY KEY DESC)";
+        Object[][] insertedRows = new Object[][]{{"a"}, {"ab"}};
+        Object[][] expectedRows = new Object[][]{{"ab"}, {"a"} };
+        runQueryTest(ddl, upsert("oid"), insertedRows, expectedRows, new WhereCondition("SUBSTR(oid, 1, 1)", "=", "'a'"));
+    }
+        
+    @Test
+    public void likeVarLengthDescPK1() throws Exception {
+        String ddl = "CREATE TABLE " + TABLE + " (oid VARCHAR PRIMARY KEY DESC)";
+        Object[][] insertedRows = new Object[][]{{"a"}, {"ab"}};
+        Object[][] expectedRows = new Object[][]{{"ab"}, {"a"} };
+        runQueryTest(ddl, upsert("oid"), insertedRows, expectedRows, new WhereCondition("oid", "like", "'a%'"));
+    }
+        
+    @Test
+    public void likeFixedLengthDescPK1() throws Exception {
+        String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(3) PRIMARY KEY DESC)";
+        Object[][] insertedRows = new Object[][]{{"a"}, {"ab"}};
+        Object[][] expectedRows = new Object[][]{{"ab"}, {"a"} };
+        runQueryTest(ddl, upsert("oid"), insertedRows, expectedRows, new WhereCondition("oid", "like", "'a%'"));
+    }
+        
+    @Test
+    public void decimalRangeDescPK1() throws Exception {
+        String ddl = "CREATE TABLE " + TABLE + " (oid DECIMAL PRIMARY KEY DESC)";
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute(ddl);
+        conn.createStatement().execute("UPSERT INTO " + TABLE + " VALUES(4.99)");
+        conn.createStatement().execute("UPSERT INTO " + TABLE + " VALUES(4.0)");
+        conn.createStatement().execute("UPSERT INTO " + TABLE + " VALUES(5.0)");
+        conn.createStatement().execute("UPSERT INTO " + TABLE + " VALUES(5.001)");
+        conn.createStatement().execute("UPSERT INTO " + TABLE + " VALUES(5.999)");
+        conn.createStatement().execute("UPSERT INTO " + TABLE + " VALUES(6.0)");
+        conn.createStatement().execute("UPSERT INTO " + TABLE + " VALUES(6.001)");
+        conn.commit();
+        
+        String query = "SELECT * FROM " + TABLE + " WHERE oid >= 5.0 AND oid < 6.0";
+        ResultSet rs = conn.createStatement().executeQuery(query);
+        assertTrue(rs.next());
+        assertTrue(new BigDecimal("5.999").compareTo(rs.getBigDecimal(1)) == 0);
+        assertTrue(rs.next());
+        assertTrue(new BigDecimal("5.001").compareTo(rs.getBigDecimal(1)) == 0);
+        assertTrue(rs.next());
+        assertTrue(new BigDecimal("5.0").compareTo(rs.getBigDecimal(1)) == 0);
+        assertFalse(rs.next());
+    }
+        
+    @Test
     public void lTrimDescCompositePK() throws Exception {
         String ddl = "CREATE TABLE " + TABLE + " (oid VARCHAR NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
         Object[][] insertedRows = new Object[][]{{" o1 ", 1}, {"  o2", 2}, {"  o3", 3}};

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
index 39baf7a..2f786ec 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
@@ -225,7 +225,7 @@ public class ExpressionCompiler extends UnsupportedAllParseNodeVisitor<Expressio
         } else {
             addBindParamMetaData(lhsNode, rhsNode, lhsExpr, rhsExpr);
         }
-        return wrapGroupByExpression(ComparisonExpression.create(op, children, context.getTempPtr()));
+        return wrapGroupByExpression(ComparisonExpression.create(op, children, context.getTempPtr(), context.getCurrentTable().getTable().rowKeyOrderOptimizable()));
     }
 
     @Override
@@ -603,7 +603,8 @@ public class ExpressionCompiler extends UnsupportedAllParseNodeVisitor<Expressio
                 expr =  convertToRoundExpressionIfNeeded(fromDataType, targetDataType, children);
             }
         }
-        return wrapGroupByExpression(CoerceExpression.create(expr, targetDataType, SortOrder.getDefault(), expr.getMaxLength()));  
+        boolean rowKeyOrderOptimizable = context.getCurrentTable().getTable().rowKeyOrderOptimizable();
+        return wrapGroupByExpression(CoerceExpression.create(expr, targetDataType, SortOrder.getDefault(), expr.getMaxLength(), rowKeyOrderOptimizable));  
     }
     
    @Override
@@ -632,7 +633,7 @@ public class ExpressionCompiler extends UnsupportedAllParseNodeVisitor<Expressio
                 context.getBindManager().addParamMetaData((BindParseNode)childNode, firstChild);
             }
         }
-        return wrapGroupByExpression(InListExpression.create(inChildren, node.isNegate(), ptr));
+        return wrapGroupByExpression(InListExpression.create(inChildren, node.isNegate(), ptr, context.getCurrentTable().getTable().rowKeyOrderOptimizable()));
     }
 
     private static final PDatum DECIMAL_DATUM = new PDatum() {
@@ -1266,7 +1267,8 @@ public class ExpressionCompiler extends UnsupportedAllParseNodeVisitor<Expressio
         // the value object array type should match the java known type
         Object[] elements = (Object[]) java.lang.reflect.Array.newInstance(theArrayElemDataType.getJavaClass(), children.size());
 
-        ArrayConstructorExpression arrayExpression = new ArrayConstructorExpression(children, arrayElemDataType);
+        boolean rowKeyOrderOptimizable = context.getCurrentTable().getTable().rowKeyOrderOptimizable();
+        ArrayConstructorExpression arrayExpression = new ArrayConstructorExpression(children, arrayElemDataType, rowKeyOrderOptimizable);
         if (ExpressionUtil.isConstant(arrayExpression)) {
             for (int i = 0; i < children.size(); i++) {
                 Expression child = children.get(i);
@@ -1281,7 +1283,7 @@ public class ExpressionCompiler extends UnsupportedAllParseNodeVisitor<Expressio
             }
             Object value = PArrayDataType.instantiatePhoenixArray(arrayElemDataType, elements);
             return LiteralExpression.newConstant(value,
-                    PDataType.fromTypeId(arrayElemDataType.getSqlType() + PDataType.ARRAY_TYPE_BASE), Determinism.ALWAYS);
+                    PDataType.fromTypeId(arrayElemDataType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, arrayExpression.getSortOrder(), Determinism.ALWAYS, rowKeyOrderOptimizable);
         }
         
         return wrapGroupByExpression(arrayExpression);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
index a270f12..6dfae7e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
@@ -63,7 +63,6 @@ import org.apache.phoenix.schema.SaltingUtil;
 import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.ValueSchema.Field;
 import org.apache.phoenix.schema.tuple.Tuple;
-import org.apache.phoenix.schema.types.PBinary;
 import org.apache.phoenix.schema.types.PChar;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.types.PVarbinary;
@@ -72,7 +71,6 @@ import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.MetaDataUtil;
 import org.apache.phoenix.util.ScanUtil;
 import org.apache.phoenix.util.SchemaUtil;
-import org.apache.phoenix.util.StringUtil;
 
 import com.google.common.collect.Iterators;
 import com.google.common.collect.Lists;
@@ -262,7 +260,6 @@ public class WhereOptimizer {
                     hasNonPointKey = true;
                 }
             }
-            keyRanges = transformKeyRangesIfNecessary(slot, context);
             
             hasMultiRanges |= keyRanges.size() > 1;
             // Force a range scan if we've encountered a multi-span slot (i.e. RVC)
@@ -322,86 +319,6 @@ public class WhereOptimizer {
         }
     }
     
-    private static int computeUnpaddedLength(byte[] b, byte padByte) {
-        int len = b.length;
-        while (len > 0 && b[len - 1] == padByte) {
-            len--;
-        }
-        return len;                                       
-    }
-    
-    // Special hack for PHOENIX-2067 to change the constant array to match
-    // the separators used for descending, variable length arrays.
-    // Note that there'd already be a coerce expression around the constant
-    // to convert it to the right type, so we shouldn't do that here.
-    private static List<KeyRange> transformKeyRangesIfNecessary(KeyExpressionVisitor.KeySlot slot, StatementContext context) {
-        KeyPart keyPart = slot.getKeyPart();
-        List<KeyRange> keyRanges = slot.getKeyRanges();
-        PColumn column = keyPart.getColumn();
-        if (column != null) {
-            PDataType type = column.getDataType();
-            PTable table = context.getCurrentTable().getTable();
-            // Constants are always build with rowKeyOptimizable as true, using the correct separators
-            // We only need to do this conversion if we have a table that has not yet been converted.
-            if (type != null && !table.rowKeyOrderOptimizable()) {
-                if (type.isArrayType() && column.getSortOrder() == SortOrder.DESC) {
-                    ImmutableBytesWritable ptr = context.getTempPtr();
-                    List<KeyRange> newKeyRanges = Lists.newArrayListWithExpectedSize(keyRanges.size());
-                    for (KeyRange keyRange : keyRanges) {
-                        byte[] lower = keyRange.getLowerRange();
-                        if (!keyRange.lowerUnbound()) {
-                            ptr.set(lower);
-                            type.coerceBytes(ptr, null, type, null, null, SortOrder.DESC, null, null, SortOrder.DESC, false);
-                            lower = ByteUtil.copyKeyBytesIfNecessary(ptr);
-                        }
-                        byte[] upper = keyRange.getUpperRange();
-                        if (!keyRange.upperUnbound()) {
-                            ptr.set(upper);
-                            type.coerceBytes(ptr, null, type, null, null, SortOrder.DESC, null, null, SortOrder.DESC, false);
-                            upper = ByteUtil.copyKeyBytesIfNecessary(ptr);
-                        }
-                        keyRange = KeyRange.getKeyRange(lower, keyRange.isLowerInclusive(), upper, keyRange.isUpperInclusive());
-                        newKeyRanges.add(keyRange);
-                    }
-                    return newKeyRanges;
-                } else if (type == PBinary.INSTANCE || (column.getSortOrder() == SortOrder.DESC && type == PChar.INSTANCE)) {
-                    // Since the table has not been upgraded, we need to replace the correct trailing byte back to the incorrect
-                    // trailing byte so that we form the correct start/stop key
-                    List<KeyRange> newKeyRanges = Lists.newArrayListWithExpectedSize(keyRanges.size());
-                    byte byteToReplace;
-                    if (type == PBinary.INSTANCE) {
-                        byteToReplace = column.getSortOrder() == SortOrder.ASC ? QueryConstants.SEPARATOR_BYTE : QueryConstants.DESC_SEPARATOR_BYTE;
-                    } else {
-                        byteToReplace = StringUtil.INVERTED_SPACE_UTF8;
-                    }
-                    for (KeyRange keyRange : keyRanges) {
-                        byte[] lower = keyRange.getLowerRange();
-                        if (!keyRange.lowerUnbound()) {
-                            int len = computeUnpaddedLength(lower, byteToReplace);
-                            if (len != lower.length) {
-                                lower = Arrays.copyOf(lower, len);
-                                lower = StringUtil.padChar(lower, lower.length);
-                            }
-                        }
-                        byte[] upper = keyRange.getUpperRange();
-                        if (!keyRange.upperUnbound()) {
-                            int len = computeUnpaddedLength(upper, byteToReplace);
-                            if (len != upper.length) {
-                                upper = Arrays.copyOf(upper, len);
-                                upper = StringUtil.padChar(upper, upper.length);
-                            }
-                        }
-                        keyRange = KeyRange.getKeyRange(lower, keyRange.isLowerInclusive(), upper, keyRange.isUpperInclusive());
-                        newKeyRanges.add(keyRange);
-                    }
-                    return newKeyRanges;
-                }
-                
-            }
-        }
-        return keyRanges;
-    }
-    
     /**
      * Get an optimal combination of key expressions for hash join key range optimization.
      * @return returns true if the entire combined expression is covered by key range optimization
@@ -464,7 +381,7 @@ public class WhereOptimizer {
             Expression lhs = count == 0 ? candidates.get(0) : new RowValueConstructorExpression(candidates.subList(0, count + 1), false);
             Expression firstRhs = count == 0 ? sampleValues.get(0).get(0) : new RowValueConstructorExpression(sampleValues.get(0).subList(0, count + 1), true);
             Expression secondRhs = count == 0 ? sampleValues.get(1).get(0) : new RowValueConstructorExpression(sampleValues.get(1).subList(0, count + 1), true);
-            Expression testExpression = InListExpression.create(Lists.newArrayList(lhs, firstRhs, secondRhs), false, context.getTempPtr());
+            Expression testExpression = InListExpression.create(Lists.newArrayList(lhs, firstRhs, secondRhs), false, context.getTempPtr(), context.getCurrentTable().getTable().rowKeyOrderOptimizable());
             remaining = pushKeyExpressionsToScan(context, statement, testExpression);
             if (context.getScanRanges().isPointLookup()) {
                 count++;
@@ -1060,16 +977,19 @@ public class WhereOptimizer {
             byte[] lowerRange = key;
             byte[] upperRange = ByteUtil.nextKey(key);
             Integer columnFixedLength = column.getMaxLength();
-            if (type.isFixedWidth() && columnFixedLength != null) {
-                if (table.rowKeyOrderOptimizable()) {
+            if (type.isFixedWidth()) {
+                if (columnFixedLength != null) { // Sanity check - should always be non null
                     // Always use minimum byte to fill as otherwise our key is bigger
                     // that it should be when the sort order is descending.
                     lowerRange = type.pad(lowerRange, columnFixedLength, SortOrder.ASC);
                     upperRange = type.pad(upperRange, columnFixedLength, SortOrder.ASC);
-                } else { // TODO: remove broken logic once tables are required to have been upgraded for PHOENIX-2067 and PHOENIX-2120
-                    lowerRange = StringUtil.padChar(lowerRange, columnFixedLength);
-                    upperRange = StringUtil.padChar(upperRange, columnFixedLength);
                 }
+            } else if (column.getSortOrder() == SortOrder.DESC && table.rowKeyOrderOptimizable()) {
+                // Append a zero byte if descending since a \xFF byte will be appended to the lowerRange
+                // causing rows to be skipped that should be included. For example, with rows 'ab', 'a',
+                // a lowerRange of 'a\xFF' would skip 'ab', while 'a\x00\xFF' would not.
+                lowerRange = Arrays.copyOf(lowerRange, lowerRange.length+1);
+                lowerRange[lowerRange.length-1] = QueryConstants.SEPARATOR_BYTE;
             }
             KeyRange keyRange = type.getKeyRange(lowerRange, true, upperRange, false);
             // Only extract LIKE expression if pattern ends with a wildcard and everything else was extracted
@@ -1430,7 +1350,7 @@ public class WhereOptimizer {
                     rhs = BaseExpression.coerce(rvc, rhs, new ExpressionComparabilityWrapper() {
 
                         @Override
-                        public Expression wrap(final Expression lhs, final Expression rhs) throws SQLException {
+                        public Expression wrap(final Expression lhs, final Expression rhs, boolean rowKeyOrderOptimizable) throws SQLException {
                             final KeyPart childPart = keySlotsIterator.next().iterator().next().getKeyPart();
                             // TODO: DelegateExpression
                             return new BaseTerminalExpression() {
@@ -1502,7 +1422,7 @@ public class WhereOptimizer {
                             };
                         }
                         
-                    });
+                    }, table.rowKeyOrderOptimizable());
                 } catch (SQLException e) {
                     return null; // Shouldn't happen
                 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/main/java/org/apache/phoenix/execute/HashJoinPlan.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/HashJoinPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/HashJoinPlan.java
index 05ef1ec..2ac728d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/HashJoinPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/HashJoinPlan.java
@@ -208,13 +208,13 @@ public class HashJoinPlan extends DelegateQueryPlan {
 
     private Expression createKeyRangeExpression(Expression lhsExpression,
             Expression rhsExpression, List<Expression> rhsValues, 
-            ImmutableBytesWritable ptr) throws SQLException {
+            ImmutableBytesWritable ptr, boolean rowKeyOrderOptimizable) throws SQLException {
         if (rhsValues.isEmpty())
             return LiteralExpression.newConstant(false, PBoolean.INSTANCE, Determinism.ALWAYS);        
         
         rhsValues.add(0, lhsExpression);
         
-        return InListExpression.create(rhsValues, false, ptr);
+        return InListExpression.create(rhsValues, false, ptr, rowKeyOrderOptimizable);
     }
 
     @Override
@@ -366,7 +366,7 @@ public class HashJoinPlan extends DelegateQueryPlan {
                 }
             }
             if (keyRangeRhsValues != null) {
-                parent.keyRangeExpressions.add(parent.createKeyRangeExpression(keyRangeLhsExpression, keyRangeRhsExpression, keyRangeRhsValues, plan.getContext().getTempPtr()));
+                parent.keyRangeExpressions.add(parent.createKeyRangeExpression(keyRangeLhsExpression, keyRangeRhsExpression, keyRangeRhsValues, plan.getContext().getTempPtr(), plan.getContext().getCurrentTable().getTable().rowKeyOrderOptimizable()));
             }
             return cache;
         }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayConstructorExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayConstructorExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayConstructorExpression.java
index d1b4a0e..d8df29a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayConstructorExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayConstructorExpression.java
@@ -19,7 +19,6 @@ import java.util.List;
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.hadoop.io.WritableUtils;
 import org.apache.phoenix.expression.visitor.ExpressionVisitor;
-import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.schema.tuple.Tuple;
 import org.apache.phoenix.schema.types.PArrayDataType;
 import org.apache.phoenix.schema.types.PDataType;
@@ -38,21 +37,23 @@ public class ArrayConstructorExpression extends BaseCompoundExpression {
     // store the offset postion in this.  Later based on the total size move this to a byte[]
     // and serialize into byte stream
     private int[] offsetPos;
+    private boolean rowKeyOrderOptimizable;
     
     public ArrayConstructorExpression() {
     }
 
-    public ArrayConstructorExpression(List<Expression> children, PDataType baseType) {
+    public ArrayConstructorExpression(List<Expression> children, PDataType baseType, boolean rowKeyOrderOptimizable) {
         super(children);
-        init(baseType);
+        init(baseType, rowKeyOrderOptimizable);
     }
 
     public ArrayConstructorExpression clone(List<Expression> children) {
-        return new ArrayConstructorExpression(children, this.baseType);
+        return new ArrayConstructorExpression(children, this.baseType, this.rowKeyOrderOptimizable);
     }
     
-    private void init(PDataType baseType) {
+    private void init(PDataType baseType, boolean rowKeyOrderOptimizable) {
         this.baseType = baseType;
+        this.rowKeyOrderOptimizable = rowKeyOrderOptimizable;
         elements = new Object[getChildren().size()];
         valuePtr.set(ByteUtil.EMPTY_BYTE_ARRAY);
         estimatedSize = PArrayDataType.estimateSize(this.children.size(), this.baseType);
@@ -113,7 +114,7 @@ public class ArrayConstructorExpression extends BaseCompoundExpression {
                             PArrayDataType.serializeNulls(oStream, nNulls);
                             offsetPos[i] = byteStream.size();
                             oStream.write(ptr.get(), ptr.getOffset(), ptr.getLength());
-                            oStream.write(QueryConstants.SEPARATOR_BYTE);
+                            oStream.write(PArrayDataType.getSeparatorByte(rowKeyOrderOptimizable, getSortOrder()));
                         }
                     } else { // No nulls for fixed length
                         oStream.write(ptr.get(), ptr.getOffset(), ptr.getLength());
@@ -123,7 +124,7 @@ public class ArrayConstructorExpression extends BaseCompoundExpression {
             if (position >= 0) position = elements.length;
             if (!baseType.isFixedWidth()) {
                 // Double seperator byte to show end of the non null array
-                PArrayDataType.writeEndSeperatorForVarLengthArray(oStream, getSortOrder());
+                PArrayDataType.writeEndSeperatorForVarLengthArray(oStream, getSortOrder(), rowKeyOrderOptimizable);
                 noOfElements = PArrayDataType.serailizeOffsetArrayIntoStream(oStream, byteStream, noOfElements,
                         offsetPos[offsetPos.length - 1], offsetPos);
                 PArrayDataType.serializeHeaderInfoIntoStream(oStream, noOfElements);
@@ -147,14 +148,23 @@ public class ArrayConstructorExpression extends BaseCompoundExpression {
     @Override
     public void readFields(DataInput input) throws IOException {
         super.readFields(input);
+        boolean rowKeyOrderOptimizable = false;
         int baseTypeOrdinal = WritableUtils.readVInt(input);
-        init(PDataType.values()[baseTypeOrdinal]);
+        if (baseTypeOrdinal < 0) {
+            rowKeyOrderOptimizable = true;
+            baseTypeOrdinal = -(baseTypeOrdinal+1);
+        }
+        init(PDataType.values()[baseTypeOrdinal], rowKeyOrderOptimizable);
     }
 
     @Override
     public void write(DataOutput output) throws IOException {
         super.write(output);
-        WritableUtils.writeVInt(output, baseType.ordinal());
+        if (rowKeyOrderOptimizable) {
+            WritableUtils.writeVInt(output, -(baseType.ordinal()+1));
+        } else {
+            WritableUtils.writeVInt(output, baseType.ordinal());
+        }
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseExpression.java
index e4f53ae..efdceac 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseExpression.java
@@ -33,12 +33,12 @@ import org.apache.phoenix.expression.function.FloorDateExpression;
 import org.apache.phoenix.expression.function.FloorDecimalExpression;
 import org.apache.phoenix.expression.function.TimeUnit;
 import org.apache.phoenix.expression.visitor.ExpressionVisitor;
-import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.TypeMismatchException;
 import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PDecimal;
 import org.apache.phoenix.schema.types.PTimestamp;
 import org.apache.phoenix.schema.types.PUnsignedTimestamp;
-import org.apache.phoenix.schema.SortOrder;
-import org.apache.phoenix.schema.TypeMismatchException;
 
 import com.google.common.collect.Lists;
 
@@ -53,7 +53,7 @@ import com.google.common.collect.Lists;
 public abstract class BaseExpression implements Expression {
     
     public static interface ExpressionComparabilityWrapper {
-        public Expression wrap(Expression lhs, Expression rhs) throws SQLException;
+        public Expression wrap(Expression lhs, Expression rhs, boolean rowKeyOrderOptimizable) throws SQLException;
     }
     
     /*
@@ -68,7 +68,7 @@ public abstract class BaseExpression implements Expression {
         WRAPPERS[CompareOp.LESS.ordinal()] = new ExpressionComparabilityWrapper() {
 
             @Override
-            public Expression wrap(Expression lhs, Expression rhs) throws SQLException {
+            public Expression wrap(Expression lhs, Expression rhs, boolean rowKeyOrderOptimizable) throws SQLException {
                 Expression e = rhs;
                 PDataType rhsType = rhs.getDataType();
                 PDataType lhsType = lhs.getDataType();
@@ -77,7 +77,7 @@ public abstract class BaseExpression implements Expression {
                 } else if ((rhsType == PTimestamp.INSTANCE || rhsType == PUnsignedTimestamp.INSTANCE)  && (lhsType != PTimestamp.INSTANCE && lhsType != PUnsignedTimestamp.INSTANCE)) {
                     e = FloorDateExpression.create(rhs, TimeUnit.MILLISECOND);
                 }
-                e = CoerceExpression.create(e, lhsType, lhs.getSortOrder(), lhs.getMaxLength());
+                e = CoerceExpression.create(e, lhsType, lhs.getSortOrder(), lhs.getMaxLength(), rowKeyOrderOptimizable);
                 return e;
             }
             
@@ -87,7 +87,7 @@ public abstract class BaseExpression implements Expression {
         WRAPPERS[CompareOp.GREATER.ordinal()] = new ExpressionComparabilityWrapper() {
 
             @Override
-            public Expression wrap(Expression lhs, Expression rhs) throws SQLException {
+            public Expression wrap(Expression lhs, Expression rhs, boolean rowKeyOrderOptimizable) throws SQLException {
                 Expression e = rhs;
                 PDataType rhsType = rhs.getDataType();
                 PDataType lhsType = lhs.getDataType();
@@ -96,7 +96,7 @@ public abstract class BaseExpression implements Expression {
                 } else if ((rhsType == PTimestamp.INSTANCE || rhsType == PUnsignedTimestamp.INSTANCE)  && (lhsType != PTimestamp.INSTANCE && lhsType != PUnsignedTimestamp.INSTANCE)) {
                     e = CeilTimestampExpression.create(rhs);
                 }
-                e = CoerceExpression.create(e, lhsType, lhs.getSortOrder(), lhs.getMaxLength());
+                e = CoerceExpression.create(e, lhsType, lhs.getSortOrder(), lhs.getMaxLength(), rowKeyOrderOptimizable);
                 return e;
             }
             
@@ -105,9 +105,9 @@ public abstract class BaseExpression implements Expression {
         WRAPPERS[CompareOp.EQUAL.ordinal()] = new ExpressionComparabilityWrapper() {
 
             @Override
-            public Expression wrap(Expression lhs, Expression rhs) throws SQLException {
+            public Expression wrap(Expression lhs, Expression rhs, boolean rowKeyOrderOptimizable) throws SQLException {
                 PDataType lhsType = lhs.getDataType();
-                Expression e = CoerceExpression.create(rhs, lhsType, lhs.getSortOrder(), lhs.getMaxLength());
+                Expression e = CoerceExpression.create(rhs, lhsType, lhs.getSortOrder(), lhs.getMaxLength(), rowKeyOrderOptimizable);
                 return e;
             }
             
@@ -127,42 +127,43 @@ public abstract class BaseExpression implements Expression {
      * @param lhs left hand side expression
      * @param rhs right hand side expression
      * @param op operator being used to compare the expressions, which can affect rounding we may need to do.
+     * @param rowKeyOrderOptimizable 
      * @return the newly coerced expression
      * @throws SQLException
      */
-    public static Expression coerce(Expression lhs, Expression rhs, CompareOp op) throws SQLException {
-        return coerce(lhs, rhs, getWrapper(op));
+    public static Expression coerce(Expression lhs, Expression rhs, CompareOp op, boolean rowKeyOrderOptimizable) throws SQLException {
+        return coerce(lhs, rhs, getWrapper(op), rowKeyOrderOptimizable);
     }
         
-    public static Expression coerce(Expression lhs, Expression rhs, ExpressionComparabilityWrapper wrapper) throws SQLException {
+    public static Expression coerce(Expression lhs, Expression rhs, ExpressionComparabilityWrapper wrapper, boolean rowKeyOrderOptimizable) throws SQLException {
         
         if (lhs instanceof RowValueConstructorExpression && rhs instanceof RowValueConstructorExpression) {
             int i = 0;
             List<Expression> coercedNodes = Lists.newArrayListWithExpectedSize(Math.max(lhs.getChildren().size(), rhs.getChildren().size()));
             for (; i < Math.min(lhs.getChildren().size(),rhs.getChildren().size()); i++) {
-                coercedNodes.add(coerce(lhs.getChildren().get(i), rhs.getChildren().get(i), wrapper));
+                coercedNodes.add(coerce(lhs.getChildren().get(i), rhs.getChildren().get(i), wrapper, rowKeyOrderOptimizable));
             }
             for (; i < lhs.getChildren().size(); i++) {
-                coercedNodes.add(coerce(lhs.getChildren().get(i), null, wrapper));
+                coercedNodes.add(coerce(lhs.getChildren().get(i), null, wrapper, rowKeyOrderOptimizable));
             }
             for (; i < rhs.getChildren().size(); i++) {
-                coercedNodes.add(coerce(null, rhs.getChildren().get(i), wrapper));
+                coercedNodes.add(coerce(null, rhs.getChildren().get(i), wrapper, rowKeyOrderOptimizable));
             }
             trimTrailingNulls(coercedNodes);
             return coercedNodes.equals(rhs.getChildren()) ? rhs : new RowValueConstructorExpression(coercedNodes, rhs.isStateless());
         } else if (lhs instanceof RowValueConstructorExpression) {
             List<Expression> coercedNodes = Lists.newArrayListWithExpectedSize(Math.max(rhs.getChildren().size(), lhs.getChildren().size()));
-            coercedNodes.add(coerce(lhs.getChildren().get(0), rhs, wrapper));
+            coercedNodes.add(coerce(lhs.getChildren().get(0), rhs, wrapper, rowKeyOrderOptimizable));
             for (int i = 1; i < lhs.getChildren().size(); i++) {
-                coercedNodes.add(coerce(lhs.getChildren().get(i), null, wrapper));
+                coercedNodes.add(coerce(lhs.getChildren().get(i), null, wrapper, rowKeyOrderOptimizable));
             }
             trimTrailingNulls(coercedNodes);
             return coercedNodes.equals(rhs.getChildren()) ? rhs : new RowValueConstructorExpression(coercedNodes, rhs.isStateless());
         } else if (rhs instanceof RowValueConstructorExpression) {
             List<Expression> coercedNodes = Lists.newArrayListWithExpectedSize(Math.max(rhs.getChildren().size(), lhs.getChildren().size()));
-            coercedNodes.add(coerce(lhs, rhs.getChildren().get(0), wrapper));
+            coercedNodes.add(coerce(lhs, rhs.getChildren().get(0), wrapper, rowKeyOrderOptimizable));
             for (int i = 1; i < rhs.getChildren().size(); i++) {
-                coercedNodes.add(coerce(null, rhs.getChildren().get(i), wrapper));
+                coercedNodes.add(coerce(null, rhs.getChildren().get(i), wrapper, rowKeyOrderOptimizable));
             }
             trimTrailingNulls(coercedNodes);
             return coercedNodes.equals(rhs.getChildren()) ? rhs : new RowValueConstructorExpression(coercedNodes, rhs.isStateless());
@@ -174,7 +175,7 @@ public abstract class BaseExpression implements Expression {
             if (rhs.getDataType() != null && lhs.getDataType() != null && !rhs.getDataType().isCastableTo(lhs.getDataType())) {
                 throw TypeMismatchException.newException(lhs.getDataType(), rhs.getDataType());
             }
-            return wrapper.wrap(lhs, rhs);
+            return wrapper.wrap(lhs, rhs, rowKeyOrderOptimizable);
         }
     }
     

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/main/java/org/apache/phoenix/expression/CoerceExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/CoerceExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/CoerceExpression.java
index b0396e8..fb6a825 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/CoerceExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/CoerceExpression.java
@@ -38,6 +38,7 @@ public class CoerceExpression extends BaseSingleExpression {
     private PDataType toType;
     private SortOrder toSortOrder;
     private Integer maxLength;
+    private boolean rowKeyOrderOptimizable;
     
     public CoerceExpression() {
     }
@@ -49,32 +50,33 @@ public class CoerceExpression extends BaseSingleExpression {
         return new CoerceExpression(expression, toType);
     }
     
-    public static Expression create(Expression expression, PDataType toType, SortOrder toSortOrder, Integer maxLength) throws SQLException {
+    public static Expression create(Expression expression, PDataType toType, SortOrder toSortOrder, Integer maxLength, boolean rowKeyOrderOptimizable) throws SQLException {
         if (toType == expression.getDataType() && toSortOrder == expression.getSortOrder()) {
             return expression;
         }
-        return new CoerceExpression(expression, toType, toSortOrder, maxLength);
+        return new CoerceExpression(expression, toType, toSortOrder, maxLength, rowKeyOrderOptimizable);
     }
     
     //Package protected for tests
     CoerceExpression(Expression expression, PDataType toType) {
-        this(expression, toType, SortOrder.getDefault(), null);
+        this(expression, toType, SortOrder.getDefault(), null, true);
     }
     
-    CoerceExpression(Expression expression, PDataType toType, SortOrder toSortOrder, Integer maxLength) {
-        this(ImmutableList.of(expression), toType, toSortOrder, maxLength);
+    CoerceExpression(Expression expression, PDataType toType, SortOrder toSortOrder, Integer maxLength, boolean rowKeyOrderOptimizable) {
+        this(ImmutableList.of(expression), toType, toSortOrder, maxLength, rowKeyOrderOptimizable);
     }
 
-    public CoerceExpression(List<Expression> children, PDataType toType, SortOrder toSortOrder, Integer maxLength) {
+    public CoerceExpression(List<Expression> children, PDataType toType, SortOrder toSortOrder, Integer maxLength, boolean rowKeyOrderOptimizable) {
         super(children);
         Preconditions.checkNotNull(toSortOrder);
         this.toType = toType;
         this.toSortOrder = toSortOrder;
         this.maxLength = maxLength;
+        this.rowKeyOrderOptimizable = rowKeyOrderOptimizable;
     }
     
     public CoerceExpression clone(List<Expression> children) {
-        return new CoerceExpression(children, this.getDataType(), this.getSortOrder(), this.getMaxLength());
+        return new CoerceExpression(children, this.getDataType(), this.getSortOrder(), this.getMaxLength(), this.rowKeyOrderOptimizable);
     }
     
     @Override
@@ -105,13 +107,19 @@ public class CoerceExpression extends BaseSingleExpression {
         if (toType == null) {
             if (other.toType != null) return false;
         } else if (!toType.equals(other.toType)) return false;
-        return true;
+        return rowKeyOrderOptimizable == other.rowKeyOrderOptimizable;
     }
 
     @Override
     public void readFields(DataInput input) throws IOException {
         super.readFields(input);
-        toType = PDataType.values()[WritableUtils.readVInt(input)];
+        int ordinal = WritableUtils.readVInt(input);
+        rowKeyOrderOptimizable = false;
+        if (ordinal < 0) {
+            rowKeyOrderOptimizable = true;
+            ordinal = -(ordinal+1);
+        }
+        toType = PDataType.values()[ordinal];
         toSortOrder = SortOrder.fromSystemValue(WritableUtils.readVInt(input));
         int byteSize = WritableUtils.readVInt(input);
         this.maxLength = byteSize == -1 ? null : byteSize;
@@ -120,16 +128,21 @@ public class CoerceExpression extends BaseSingleExpression {
     @Override
     public void write(DataOutput output) throws IOException {
         super.write(output);
-        WritableUtils.writeVInt(output, toType.ordinal());
+        if (rowKeyOrderOptimizable) {
+            WritableUtils.writeVInt(output, -(toType.ordinal()+1));
+        } else {
+            WritableUtils.writeVInt(output, toType.ordinal());
+        }
         WritableUtils.writeVInt(output, toSortOrder.getSystemValue());
         WritableUtils.writeVInt(output, maxLength == null ? -1 : maxLength);
     }
-    
+
     @Override
     public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
         if (getChild().evaluate(tuple, ptr)) {
-            getDataType().coerceBytes(ptr, getChild().getDataType(), getChild().getSortOrder(), getSortOrder(),
-                    getChild().getMaxLength());
+            getDataType().coerceBytes(ptr, null, getChild().getDataType(),
+                    getChild().getMaxLength(), null, getChild().getSortOrder(), 
+                    maxLength, null, getSortOrder(), rowKeyOrderOptimizable);
             return true;
         }
         return false;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java
index b9190e2..1c8df20 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java
@@ -59,7 +59,7 @@ import com.google.common.collect.Lists;
 public class ComparisonExpression extends BaseCompoundExpression {
     private CompareOp op;
     
-    private static void addEqualityExpression(Expression lhs, Expression rhs, List<Expression> andNodes, ImmutableBytesWritable ptr) throws SQLException {
+    private static void addEqualityExpression(Expression lhs, Expression rhs, List<Expression> andNodes, ImmutableBytesWritable ptr, boolean rowKeyOrderOptimizable) throws SQLException {
         boolean isLHSNull = ExpressionUtil.isNull(lhs, ptr);
         boolean isRHSNull = ExpressionUtil.isNull(rhs, ptr);
         if (isLHSNull && isRHSNull) { // null == null will end up making the query degenerate
@@ -69,7 +69,7 @@ public class ComparisonExpression extends BaseCompoundExpression {
         } else if (isRHSNull) { // AND lhs IS NULL
             andNodes.add(IsNullExpression.create(lhs, false, ptr));
         } else { // AND lhs = rhs
-            andNodes.add(ComparisonExpression.create(CompareOp.EQUAL, Arrays.asList(lhs, rhs), ptr));
+            andNodes.add(ComparisonExpression.create(CompareOp.EQUAL, Arrays.asList(lhs, rhs), ptr, rowKeyOrderOptimizable));
         }
     }
     
@@ -81,32 +81,32 @@ public class ComparisonExpression extends BaseCompoundExpression {
      * @param andNodes
      * @throws SQLException 
      */
-    private static void rewriteRVCAsEqualityExpression(Expression lhs, Expression rhs, List<Expression> andNodes, ImmutableBytesWritable ptr) throws SQLException {
+    private static void rewriteRVCAsEqualityExpression(Expression lhs, Expression rhs, List<Expression> andNodes, ImmutableBytesWritable ptr, boolean rowKeyOrderOptimizable) throws SQLException {
         if (lhs instanceof RowValueConstructorExpression && rhs instanceof RowValueConstructorExpression) {
             int i = 0;
             for (; i < Math.min(lhs.getChildren().size(),rhs.getChildren().size()); i++) {
-                addEqualityExpression(lhs.getChildren().get(i), rhs.getChildren().get(i), andNodes, ptr);
+                addEqualityExpression(lhs.getChildren().get(i), rhs.getChildren().get(i), andNodes, ptr, rowKeyOrderOptimizable);
             }
             for (; i < lhs.getChildren().size(); i++) {
-                addEqualityExpression(lhs.getChildren().get(i), LiteralExpression.newConstant(null, lhs.getChildren().get(i).getDataType()), andNodes, ptr);
+                addEqualityExpression(lhs.getChildren().get(i), LiteralExpression.newConstant(null, lhs.getChildren().get(i).getDataType()), andNodes, ptr, rowKeyOrderOptimizable);
             }
             for (; i < rhs.getChildren().size(); i++) {
-                addEqualityExpression(LiteralExpression.newConstant(null, rhs.getChildren().get(i).getDataType()), rhs.getChildren().get(i), andNodes, ptr);
+                addEqualityExpression(LiteralExpression.newConstant(null, rhs.getChildren().get(i).getDataType()), rhs.getChildren().get(i), andNodes, ptr, rowKeyOrderOptimizable);
             }
         } else if (lhs instanceof RowValueConstructorExpression) {
-            addEqualityExpression(lhs.getChildren().get(0), rhs, andNodes, ptr);
+            addEqualityExpression(lhs.getChildren().get(0), rhs, andNodes, ptr, rowKeyOrderOptimizable);
             for (int i = 1; i < lhs.getChildren().size(); i++) {
-                addEqualityExpression(lhs.getChildren().get(i), LiteralExpression.newConstant(null, lhs.getChildren().get(i).getDataType()), andNodes, ptr);
+                addEqualityExpression(lhs.getChildren().get(i), LiteralExpression.newConstant(null, lhs.getChildren().get(i).getDataType()), andNodes, ptr, rowKeyOrderOptimizable);
             }
         } else if (rhs instanceof RowValueConstructorExpression) {
-            addEqualityExpression(lhs, rhs.getChildren().get(0), andNodes, ptr);
+            addEqualityExpression(lhs, rhs.getChildren().get(0), andNodes, ptr, rowKeyOrderOptimizable);
             for (int i = 1; i < rhs.getChildren().size(); i++) {
-                addEqualityExpression(LiteralExpression.newConstant(null, rhs.getChildren().get(i).getDataType()), rhs.getChildren().get(i), andNodes, ptr);
+                addEqualityExpression(LiteralExpression.newConstant(null, rhs.getChildren().get(i).getDataType()), rhs.getChildren().get(i), andNodes, ptr, rowKeyOrderOptimizable);
             }
         }
     }
     
-    public static Expression create(CompareOp op, List<Expression> children, ImmutableBytesWritable ptr) throws SQLException {
+    public static Expression create(CompareOp op, List<Expression> children, ImmutableBytesWritable ptr, boolean rowKeyOrderOptimizable) throws SQLException {
         Expression lhsExpr = children.get(0);
         Expression rhsExpr = children.get(1);
         PDataType lhsExprDataType = lhsExpr.getDataType();
@@ -115,14 +115,14 @@ public class ComparisonExpression extends BaseCompoundExpression {
         if ((lhsExpr instanceof RowValueConstructorExpression || rhsExpr instanceof RowValueConstructorExpression) && !(lhsExpr instanceof ArrayElemRefExpression) && !(rhsExpr instanceof ArrayElemRefExpression)) {
             if (op == CompareOp.EQUAL || op == CompareOp.NOT_EQUAL) {
                 List<Expression> andNodes = Lists.<Expression>newArrayListWithExpectedSize(Math.max(lhsExpr.getChildren().size(), rhsExpr.getChildren().size()));
-                rewriteRVCAsEqualityExpression(lhsExpr, rhsExpr, andNodes, ptr);
+                rewriteRVCAsEqualityExpression(lhsExpr, rhsExpr, andNodes, ptr, rowKeyOrderOptimizable);
                 Expression expr = AndExpression.create(andNodes);
                 if (op == CompareOp.NOT_EQUAL) {
                     expr = NotExpression.create(expr, ptr);
                 }
                 return expr;
             }
-            rhsExpr = RowValueConstructorExpression.coerce(lhsExpr, rhsExpr, op);
+            rhsExpr = RowValueConstructorExpression.coerce(lhsExpr, rhsExpr, op, rowKeyOrderOptimizable);
             // Always wrap both sides in row value constructor, so we don't have to consider comparing
             // a non rvc with a rvc.
             if ( ! ( lhsExpr instanceof RowValueConstructorExpression ) ) {
@@ -164,11 +164,13 @@ public class ComparisonExpression extends BaseCompoundExpression {
             // into account the comparison operator.
             if (rhsExprDataType != lhsExprDataType 
                     || rhsExpr.getSortOrder() != lhsExpr.getSortOrder()
-                    || (rhsExprDataType.isFixedWidth() && rhsExpr.getMaxLength() != null && lhsExprDataType.isFixedWidth() && lhsExpr.getMaxLength() != null && rhsExpr.getMaxLength() < lhsExpr.getMaxLength())) {
+                    || (rhsExprDataType.isFixedWidth() && rhsExpr.getMaxLength() != null && 
+                        lhsExprDataType.isFixedWidth() && lhsExpr.getMaxLength() != null && 
+                        rhsExpr.getMaxLength() < lhsExpr.getMaxLength())) {
                 // TODO: if lengths are unequal and fixed width?
                 if (rhsExprDataType.isCoercibleTo(lhsExprDataType, rhsValue)) { // will convert 2.0 -> 2
                     children = Arrays.asList(children.get(0), LiteralExpression.newConstant(rhsValue, lhsExprDataType, 
-                            lhsExpr.getMaxLength(), null, lhsExpr.getSortOrder(), determinism));
+                            lhsExpr.getMaxLength(), null, lhsExpr.getSortOrder(), determinism, rowKeyOrderOptimizable));
                 } else if (op == CompareOp.EQUAL) {
                     return LiteralExpression.newConstant(false, PBoolean.INSTANCE, Determinism.ALWAYS);
                 } else if (op == CompareOp.NOT_EQUAL) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/main/java/org/apache/phoenix/expression/InListExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/InListExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/InListExpression.java
index 63178db..b6d5a24 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/InListExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/InListExpression.java
@@ -39,6 +39,7 @@ import org.apache.phoenix.schema.types.PBoolean;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.ExpressionUtil;
+import org.apache.phoenix.util.StringUtil;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
@@ -56,15 +57,17 @@ public class InListExpression extends BaseSingleExpression {
     private int valuesByteLength;
     private int fixedWidth = -1;
     private List<Expression> keyExpressions; // client side only
+    private boolean rowKeyOrderOptimizable; // client side only
 
-    public static Expression create (List<Expression> children, boolean isNegate, ImmutableBytesWritable ptr) throws SQLException {
+
+    public static Expression create (List<Expression> children, boolean isNegate, ImmutableBytesWritable ptr, boolean rowKeyOrderOptimizable) throws SQLException {
         Expression firstChild = children.get(0);
         
         if (firstChild.isStateless() && (!firstChild.evaluate(null, ptr) || ptr.getLength() == 0)) {
             return LiteralExpression.newConstant(null, PBoolean.INSTANCE, firstChild.getDeterminism());
         }
         if (children.size() == 2) {
-            return ComparisonExpression.create(isNegate ? CompareOp.NOT_EQUAL : CompareOp.EQUAL, children, ptr);
+            return ComparisonExpression.create(isNegate ? CompareOp.NOT_EQUAL : CompareOp.EQUAL, children, ptr, rowKeyOrderOptimizable);
         }
         
         boolean addedNull = false;
@@ -73,7 +76,7 @@ public class InListExpression extends BaseSingleExpression {
         coercedKeyExpressions.add(firstChild);
         for (int i = 1; i < children.size(); i++) {
             try {
-                Expression rhs = BaseExpression.coerce(firstChild, children.get(i), CompareOp.EQUAL);
+                Expression rhs = BaseExpression.coerce(firstChild, children.get(i), CompareOp.EQUAL, rowKeyOrderOptimizable);
                 coercedKeyExpressions.add(rhs);
             } catch (SQLException e) {
                 // Type mismatch exception or invalid data exception.
@@ -89,7 +92,7 @@ public class InListExpression extends BaseSingleExpression {
         if (coercedKeyExpressions.size() == 2 && addedNull) {
             return LiteralExpression.newConstant(null, PBoolean.INSTANCE, Determinism.ALWAYS);
         }
-        Expression expression = new InListExpression(coercedKeyExpressions);
+        Expression expression = new InListExpression(coercedKeyExpressions, rowKeyOrderOptimizable);
         if (isNegate) { 
             expression = NotExpression.create(expression, ptr);
         }
@@ -102,10 +105,13 @@ public class InListExpression extends BaseSingleExpression {
     public InListExpression() {
     }
 
-    public InListExpression(List<Expression> keyExpressions) {
+    public InListExpression(List<Expression> keyExpressions, boolean rowKeyOrderOptimizable) {
         super(keyExpressions.get(0));
+        this.rowKeyOrderOptimizable = rowKeyOrderOptimizable;
+        Expression firstChild = keyExpressions.get(0);
         this.keyExpressions = keyExpressions.subList(1, keyExpressions.size());
         Set<ImmutableBytesPtr> values = Sets.newHashSetWithExpectedSize(keyExpressions.size()-1);
+        Integer maxLength = firstChild.getDataType().isFixedWidth() ? firstChild.getMaxLength() : null;
         int fixedWidth = -1;
         boolean isFixedLength = true;
         for (int i = 1; i < keyExpressions.size(); i++) {
@@ -113,6 +119,12 @@ public class InListExpression extends BaseSingleExpression {
             Expression child = keyExpressions.get(i);
             child.evaluate(null, ptr);
             if (ptr.getLength() > 0) { // filter null as it has no impact
+                if (rowKeyOrderOptimizable) {
+                    firstChild.getDataType().pad(ptr, maxLength, firstChild.getSortOrder());
+                } else if (maxLength != null) {
+                    byte[] paddedBytes = StringUtil.padChar(ByteUtil.copyKeyBytesIfNecessary(ptr), maxLength);
+                    ptr.set(paddedBytes);
+                }
                 if (values.add(ptr)) {
                     int length = ptr.getLength();
                     if (fixedWidth == -1) {
@@ -274,4 +286,8 @@ public class InListExpression extends BaseSingleExpression {
         buf.setCharAt(buf.length()-1,')');
         return buf.toString();
     }
+
+    public InListExpression clone(List<Expression> l) {
+        return new InListExpression(l, this.rowKeyOrderOptimizable);
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/main/java/org/apache/phoenix/expression/LiteralExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/LiteralExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/LiteralExpression.java
index c1faf66..05bd9b3 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/LiteralExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/LiteralExpression.java
@@ -28,6 +28,7 @@ import org.apache.phoenix.expression.visitor.ExpressionVisitor;
 import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.TypeMismatchException;
 import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.PArrayDataType;
 import org.apache.phoenix.schema.types.PBoolean;
 import org.apache.phoenix.schema.types.PChar;
 import org.apache.phoenix.schema.types.PDataType;
@@ -37,6 +38,7 @@ import org.apache.phoenix.schema.types.PTimestamp;
 import org.apache.phoenix.schema.types.PVarchar;
 import org.apache.phoenix.schema.types.PhoenixArray;
 import org.apache.phoenix.util.ByteUtil;
+import org.apache.phoenix.util.StringUtil;
 
 import com.google.common.base.Preconditions;
 
@@ -150,8 +152,13 @@ public class LiteralExpression extends BaseTerminalExpression {
         return newConstant(value, type, maxLength, scale, SortOrder.getDefault(), determinism);
     }
 
+    public static LiteralExpression newConstant(Object value, PDataType type, Integer maxLength, Integer scale, SortOrder sortOrder, Determinism determinism) 
+            throws SQLException {
+        return newConstant(value, type, maxLength, scale, sortOrder, determinism, true);
+    }
+    
     // TODO: cache?
-    public static LiteralExpression newConstant(Object value, PDataType type, Integer maxLength, Integer scale, SortOrder sortOrder, Determinism determinism)
+    public static LiteralExpression newConstant(Object value, PDataType type, Integer maxLength, Integer scale, SortOrder sortOrder, Determinism determinism, boolean rowKeyOrderOptimizable)
             throws SQLException {
         if (value == null) {
             return  (type == null) ?  getNullLiteralExpression(determinism) : getTypedNullLiteralExpression(type, determinism);
@@ -170,10 +177,15 @@ public class LiteralExpression extends BaseTerminalExpression {
             throw TypeMismatchException.newException(type, actualType, value.toString());
         }
         value = type.toObject(value, actualType);
-        byte[] b = type.toBytes(value, sortOrder);
+        byte[] b = type.isArrayType() ? ((PArrayDataType)type).toBytes(value, PArrayDataType.arrayBaseType(type), sortOrder, rowKeyOrderOptimizable) :
+                type.toBytes(value, sortOrder);
         if (type == PVarchar.INSTANCE || type == PChar.INSTANCE) {
             if (type == PChar.INSTANCE && maxLength != null  && b.length < maxLength) {
-                b = type.pad(b, maxLength, sortOrder);
+                if (rowKeyOrderOptimizable) {
+                    b = type.pad(b, maxLength, sortOrder);
+                } else {
+                    b = StringUtil.padChar(b, maxLength);
+                }
             } else if (value != null) {
                 maxLength = ((String)value).length();
             }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InvertFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InvertFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InvertFunction.java
index 6a3e2a1..3615cbe 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InvertFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InvertFunction.java
@@ -47,9 +47,9 @@ public class InvertFunction extends ScalarFunction {
     public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
         if (!getChildExpression().evaluate(tuple, ptr)) { return false; }
         if (ptr.getLength() == 0) { return true; }
-        byte[] buf = new byte[ptr.getLength()];
-        SortOrder.invert(ptr.get(), ptr.getOffset(), buf, 0, ptr.getLength());
-        ptr.set(buf);
+        PDataType type = getDataType();
+        // FIXME: losing rowKeyOrderOptimizable here
+        type.coerceBytes(ptr, type, getChildExpression().getSortOrder(), getSortOrder());
         return true;
     }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PrefixFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PrefixFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PrefixFunction.java
index 111c8b3..cb98e28 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PrefixFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PrefixFunction.java
@@ -18,6 +18,7 @@
 
 package org.apache.phoenix.expression.function;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
@@ -25,6 +26,7 @@ import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
 import org.apache.phoenix.compile.KeyPart;
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.query.KeyRange;
+import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.schema.PColumn;
 import org.apache.phoenix.schema.PTable;
 import org.apache.phoenix.schema.SortOrder;
@@ -84,14 +86,28 @@ abstract public class PrefixFunction extends ScalarFunction {
                 default:
                     return childPart.getKeyRange(op, rhs);
                 }
-                Integer length = getColumn().getMaxLength();
-                SortOrder sortOrder = getColumn().getSortOrder();
-                if (type.isFixedWidth() && length != null) {
-                    if (lowerRange != KeyRange.UNBOUND) {
-                        lowerRange = type.pad(lowerRange, length, sortOrder);
+                PColumn column = getColumn();
+                Integer length = column.getMaxLength();
+                if (type.isFixedWidth()) {
+                    if (length != null) { // Sanity check - shouldn't be necessary
+                        // Don't pad based on current sort order, but instead use our
+                        // minimum byte as otherwise we'll end up skipping rows in
+                        // the case of descending, since rows with more padding appear
+                        // *after* rows with no padding.
+                        if (lowerRange != KeyRange.UNBOUND) {
+                            lowerRange = type.pad(lowerRange, length, SortOrder.ASC);
+                        }
+                        if (upperRange != KeyRange.UNBOUND) {
+                            upperRange = type.pad(upperRange, length, SortOrder.ASC);
+                        }
                     }
-                    if (upperRange != KeyRange.UNBOUND) {
-                        upperRange = type.pad(upperRange, length, sortOrder);
+                } else if (column.getSortOrder() == SortOrder.DESC && getTable().rowKeyOrderOptimizable()) {
+                    // Append a zero byte if descending since a \xFF byte will be appended to the lowerRange
+                    // causing rows to be skipped that should be included. For example, with rows 'ab', 'a',
+                    // a lowerRange of 'a\xFF' would skip 'ab', while 'a\x00\xFF' would not.
+                    if (lowerRange != KeyRange.UNBOUND) {
+                        lowerRange = Arrays.copyOf(lowerRange, lowerRange.length+1);
+                        lowerRange[lowerRange.length-1] = QueryConstants.SEPARATOR_BYTE;
                     }
                 }
                 return KeyRange.getKeyRange(lowerRange, lowerInclusive, upperRange, false);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RTrimFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RTrimFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RTrimFunction.java
index aa632e2..5713713 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RTrimFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RTrimFunction.java
@@ -18,6 +18,7 @@
 package org.apache.phoenix.expression.function;
 
 import java.sql.SQLException;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
@@ -28,6 +29,7 @@ import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.parse.FunctionParseNode.Argument;
 import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
 import org.apache.phoenix.query.KeyRange;
+import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.schema.PColumn;
 import org.apache.phoenix.schema.PTable;
 import org.apache.phoenix.schema.SortOrder;
@@ -109,35 +111,70 @@ public class RTrimFunction extends ScalarFunction {
                 byte[] lowerRange = KeyRange.UNBOUND;
                 byte[] upperRange = KeyRange.UNBOUND;
                 boolean lowerInclusive = true;
+                boolean upperInclusive = false;
                 
                 PDataType type = getColumn().getDataType();
+                SortOrder sortOrder = getColumn().getSortOrder();
                 switch (op) {
-                case EQUAL:
-                    lowerRange = evaluateExpression(rhs);
-                    upperRange = ByteUtil.nextKey(ByteUtil.concat(lowerRange, new byte[] {StringUtil.SPACE_UTF8}));
-                    break;
                 case LESS_OR_EQUAL:
                     lowerInclusive = false;
-                    upperRange = ByteUtil.nextKey(ByteUtil.concat(evaluateExpression(rhs), new byte[] {StringUtil.SPACE_UTF8}));
+                case EQUAL:
+                    upperRange = evaluateExpression(rhs);
+                    if (op == CompareOp.EQUAL) {
+                        lowerRange = upperRange;
+                    }
+                    if (sortOrder == SortOrder.ASC || !getTable().rowKeyOrderOptimizable()) {
+                        upperRange = Arrays.copyOf(upperRange, upperRange.length + 1);
+                        upperRange[upperRange.length-1] = StringUtil.SPACE_UTF8;
+                        ByteUtil.nextKey(upperRange, upperRange.length);
+                    } else {
+                        upperInclusive = true;
+                        if (op == CompareOp.LESS_OR_EQUAL) {
+                            // Nothing more to do here, as the biggest value for DESC
+                            // will be the RHS value.
+                            break;
+                        }
+                        /*
+                         * Somewhat tricky to get the range correct for the DESC equality case.
+                         * The lower range is the RHS value followed by any number of inverted spaces.
+                         * We need to add a zero byte as the lower range will have an \xFF byte
+                         * appended to it and otherwise we'd skip past any rows where there is more
+                         * than one space following the RHS.
+                         * The upper range should span up to and including the RHS value. We need
+                         * to add our own \xFF as otherwise this will look like a degenerate query
+                         * since the lower would be bigger than the upper range.
+                         */
+                        lowerRange = Arrays.copyOf(lowerRange, lowerRange.length + 2);
+                        lowerRange[lowerRange.length-2] = StringUtil.INVERTED_SPACE_UTF8;
+                        lowerRange[lowerRange.length-1] = QueryConstants.SEPARATOR_BYTE;
+                        upperRange = Arrays.copyOf(upperRange, upperRange.length + 1);
+                        upperRange[upperRange.length-1] = QueryConstants.DESC_SEPARATOR_BYTE;
+                    }
                     break;
                 default:
+                    // TOOD: Is this ok for DESC?
                     return childPart.getKeyRange(op, rhs);
                 }
                 Integer length = getColumn().getMaxLength();
-                SortOrder sortOrder = getColumn().getSortOrder();
                 if (type.isFixedWidth() && length != null) {
+                    // Don't pad based on current sort order, but instead use our
+                    // minimum byte as otherwise we'll end up skipping rows in
+                    // the case of descending, since rows with more padding appear
+                    // *after* rows with no padding.
                     if (lowerRange != KeyRange.UNBOUND) {
-                        lowerRange = type.pad(lowerRange, length, sortOrder);
+                        lowerRange = type.pad(lowerRange, length, SortOrder.ASC);
                     }
                     if (upperRange != KeyRange.UNBOUND) {
-                        upperRange = type.pad(upperRange, length, sortOrder);
+                        upperRange = type.pad(upperRange, length, SortOrder.ASC);
                     }
                 }
-                return KeyRange.getKeyRange(lowerRange, lowerInclusive, upperRange, false);
+                return KeyRange.getKeyRange(lowerRange, lowerInclusive, upperRange, upperInclusive);
             }
 
             @Override
             public List<Expression> getExtractNodes() {
+                // We cannot extract the node, as we may have false positives with trailing
+                // non blank characters such as 'foo  bar' where the RHS constant is 'foo'.
                 return Collections.<Expression>emptyList();
             }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/CloneExpressionVisitor.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/CloneExpressionVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/CloneExpressionVisitor.java
index b252358..55f227f 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/CloneExpressionVisitor.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/CloneExpressionVisitor.java
@@ -136,7 +136,7 @@ public class CloneExpressionVisitor extends TraverseAllExpressionVisitor<Express
 
     @Override
     public Expression visitLeave(InListExpression node, List<Expression> l) {
-        return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node :  new InListExpression(l);
+        return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node :  node.clone(l);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
index bad02e4..6236184 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
@@ -79,7 +79,7 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
         super(sqlTypeName, sqlType, clazz, codec, ordinal);
     }
 
-    private static byte getSeparatorByte(boolean rowKeyOrderOptimizable, SortOrder sortOrder) {
+    public static byte getSeparatorByte(boolean rowKeyOrderOptimizable, SortOrder sortOrder) {
         return SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable, false, sortOrder);
     }
 
@@ -177,7 +177,7 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
         writeEndSeperatorForVarLengthArray(oStream, sortOrder, true);
     }
     
-    private static void writeEndSeperatorForVarLengthArray(DataOutputStream oStream, SortOrder sortOrder, boolean rowKeyOrderOptimizable)
+    public static void writeEndSeperatorForVarLengthArray(DataOutputStream oStream, SortOrder sortOrder, boolean rowKeyOrderOptimizable)
             throws IOException {
         byte sepByte = getSeparatorByte(rowKeyOrderOptimizable, sortOrder);
         oStream.write(sepByte);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java b/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
index 3f09518..96b8ea2 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
@@ -1669,6 +1669,14 @@ public abstract class BaseTest {
         fail("Unable to find " + results + " in " + Arrays.asList(expectedResultsArray));
     }
 
+    protected void assertValueEqualsResultSet(ResultSet rs, List<Object> expectedResults) throws SQLException {
+        List<List<Object>> nestedExpectedResults = Lists.newArrayListWithExpectedSize(expectedResults.size());
+        for (Object expectedResult : expectedResults) {
+            nestedExpectedResults.add(Arrays.asList(expectedResult));
+        }
+        assertValuesEqualsResultSet(rs, nestedExpectedResults); 
+    }
+
     /**
      * Asserts that we find the expected values in the result set. We don't know the order, since we don't always
      * have an order by and we're going through indexes, but we assert that each expected result occurs once as

http://git-wip-us.apache.org/repos/asf/phoenix/blob/498cc552/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java b/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
index 66695f8..15e3583 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
@@ -321,7 +321,7 @@ public class TestUtil {
     }
 
     public static Expression in(Expression... expressions) throws SQLException {
-        return InListExpression.create(Arrays.asList(expressions), false, new ImmutableBytesWritable());
+        return InListExpression.create(Arrays.asList(expressions), false, new ImmutableBytesWritable(), true);
     }
 
     public static Expression in(Expression e, Object... literals) throws SQLException {
@@ -331,7 +331,7 @@ public class TestUtil {
         for (Object o : literals) {
             expressions.add(LiteralExpression.newConstant(o, childType));
         }
-        return InListExpression.create(expressions, false, new ImmutableBytesWritable());
+        return InListExpression.create(expressions, false, new ImmutableBytesWritable(), true);
     }
 
     public static void assertDegenerate(StatementContext context) {


[34/40] phoenix git commit: PHOENIX-1673 Allow TenantId to be of any integral data type

Posted by ma...@apache.org.
PHOENIX-1673 Allow TenantId to be of any integral data type


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/5c048430
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/5c048430
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/5c048430

Branch: refs/heads/calcite
Commit: 5c048430ed39ce23f95609607c1bd845401900a9
Parents: b28686f
Author: Jeffrey Lyons <Je...@d2l.com>
Authored: Thu Jul 9 10:07:40 2015 -0400
Committer: Eli Levine <el...@apache.org>
Committed: Thu Aug 13 11:01:00 2015 -0700

----------------------------------------------------------------------
 .../end2end/BaseTenantSpecificViewIndexIT.java  |  33 ++-
 .../apache/phoenix/end2end/CreateTableIT.java   |  25 ++
 .../apache/phoenix/end2end/TenantIdTypeIT.java  | 226 ++++++++++++++
 .../end2end/TenantSpecificTablesDDLIT.java      |  12 -
 .../end2end/TenantSpecificViewIndexIT.java      |   5 +
 .../apache/phoenix/compile/DeleteCompiler.java  |   3 +-
 .../apache/phoenix/compile/UpsertCompiler.java  |   3 +-
 .../apache/phoenix/compile/WhereOptimizer.java  |  11 +-
 .../phoenix/exception/SQLExceptionCode.java     |   3 +-
 .../apache/phoenix/execute/BaseQueryPlan.java   |  14 +-
 .../apache/phoenix/execute/MutationState.java   |  23 +-
 .../apache/phoenix/schema/MetaDataClient.java   |   4 +-
 .../java/org/apache/phoenix/util/ScanUtil.java  |  35 ++-
 .../util/TenantIdByteConversionTest.java        | 294 +++++++++++++++++++
 14 files changed, 631 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/5c048430/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseTenantSpecificViewIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseTenantSpecificViewIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseTenantSpecificViewIndexIT.java
index 93fc222..b450643 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseTenantSpecificViewIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseTenantSpecificViewIndexIT.java
@@ -40,6 +40,7 @@ public class BaseTenantSpecificViewIndexIT extends BaseHBaseManagedTimeIT {
     
     public static final String TENANT1_ID = "tenant1";
     public static final String TENANT2_ID = "tenant2";
+    public static final String NON_STRING_TENANT_ID = "1234";
     
     protected Set<Pair<String, String>> tenantViewsToDelete = newHashSet();
     
@@ -48,7 +49,7 @@ public class BaseTenantSpecificViewIndexIT extends BaseHBaseManagedTimeIT {
     }
     
     protected void testUpdatableView(Integer saltBuckets, boolean localIndex) throws Exception {
-        createBaseTable("t", saltBuckets);
+        createBaseTable("t", saltBuckets, true);
         Connection conn = createTenantConnection(TENANT1_ID);
         try {
             createAndPopulateTenantView(conn, TENANT1_ID, "t", "");
@@ -58,13 +59,25 @@ public class BaseTenantSpecificViewIndexIT extends BaseHBaseManagedTimeIT {
             try { conn.close();} catch (Exception ignored) {}
         }
     }
+
+    protected void testUpdatableViewNonString(Integer saltBuckets, boolean localIndex) throws Exception {
+        createBaseTable("t", saltBuckets, false);
+        Connection conn = createTenantConnection(NON_STRING_TENANT_ID);
+        try {
+            createAndPopulateTenantView(conn, NON_STRING_TENANT_ID, "t", "");
+            createAndVerifyIndexNonStringTenantId(conn, NON_STRING_TENANT_ID, "");
+            verifyViewData(conn, "");
+        } finally {
+            try { conn.close();} catch (Exception ignored) {}
+        }
+    }
     
     protected void testUpdatableViewsWithSameNameDifferentTenants(Integer saltBuckets) throws Exception {
         testUpdatableViewsWithSameNameDifferentTenants(saltBuckets, false);
     }
 
     protected void testUpdatableViewsWithSameNameDifferentTenants(Integer saltBuckets, boolean localIndex) throws Exception {
-        createBaseTable("t", saltBuckets);
+        createBaseTable("t", saltBuckets, true);
         Connection conn1 = createTenantConnection(TENANT1_ID);
         Connection conn2 = createTenantConnection(TENANT2_ID);
         try {
@@ -86,9 +99,10 @@ public class BaseTenantSpecificViewIndexIT extends BaseHBaseManagedTimeIT {
         }
     }
     
-    private void createBaseTable(String tableName, Integer saltBuckets) throws SQLException {
+    private void createBaseTable(String tableName, Integer saltBuckets, boolean hasStringTenantId) throws SQLException {
         Connection conn = DriverManager.getConnection(getUrl());
-        String ddl = "CREATE TABLE " + tableName + " (t_id VARCHAR NOT NULL,\n" +
+        String tenantIdType = hasStringTenantId ? "VARCHAR" : "BIGINT";
+        String ddl = "CREATE TABLE " + tableName + " (t_id " + tenantIdType + " NOT NULL,\n" +
                 "k1 INTEGER NOT NULL,\n" +
                 "k2 INTEGER NOT NULL,\n" +
                 "v1 VARCHAR,\n" +
@@ -135,6 +149,17 @@ public class BaseTenantSpecificViewIndexIT extends BaseHBaseManagedTimeIT {
             assertEquals(expected, QueryUtil.getExplainPlan(rs));
         }
     }
+
+    private void createAndVerifyIndexNonStringTenantId(Connection conn, String tenantId, String valuePrefix) throws SQLException {
+        conn.createStatement().execute("CREATE LOCAL INDEX i ON v(v2)");
+        conn.createStatement().execute("UPSERT INTO v(k2,v1,v2) VALUES (-1, 'blah', 'superblah')"); // sanity check that we can upsert after index is there
+        conn.commit();
+        ResultSet rs = conn.createStatement().executeQuery("EXPLAIN SELECT k1, k2, v2 FROM v WHERE v2='" + valuePrefix + "v2-1'");
+        assertEquals(
+                "CLIENT PARALLEL 1-WAY RANGE SCAN OVER _LOCAL_IDX_T [" + tenantId + ",-32768,'" + valuePrefix + "v2-1']\n"
+                        + "    SERVER FILTER BY FIRST KEY ONLY\n"
+                        + "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
+    }
     
     private Connection createTenantConnection(String tenantId) throws SQLException {
         Properties props = new Properties();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5c048430/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java
index 31abd9b..7c4576c 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java
@@ -105,6 +105,31 @@ public class CreateTableIT extends BaseClientManagedTimeIT {
         conn = DriverManager.getConnection(getUrl(), props);
         conn.createStatement().execute("DROP TABLE m_interface_job");
     }
+
+    @Test
+    public void testCreateMultiTenantTable() throws Exception {
+        long ts = nextTimestamp();
+        Properties props = new Properties();
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts));
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        String ddl = "CREATE TABLE m_multi_tenant_test(                TenantId UNSIGNED_INT NOT NULL ,\n" +
+                "                Id UNSIGNED_INT NOT NULL ,\n" +
+                "                val VARCHAR ,\n" +
+                "                CONSTRAINT pk PRIMARY KEY(TenantId, Id) \n" +
+                "                ) MULTI_TENANT=true";
+        conn.createStatement().execute(ddl);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 10));
+        conn = DriverManager.getConnection(getUrl(), props);
+        try {
+            conn.createStatement().execute(ddl);
+            fail();
+        } catch (TableAlreadyExistsException e) {
+            // expected
+        }
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 20));
+        conn = DriverManager.getConnection(getUrl(), props);
+        conn.createStatement().execute("DROP TABLE m_multi_tenant_test");
+    }
     
     /**
      * Test that when the ddl only has PK cols, ttl is set.

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5c048430/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantIdTypeIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantIdTypeIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantIdTypeIT.java
new file mode 100644
index 0000000..f28436e
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantIdTypeIT.java
@@ -0,0 +1,226 @@
+/*
+ * 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.phoenix.end2end;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.sql.*;
+import java.util.Properties;
+import java.util.Collection;
+import java.util.List;
+import com.google.common.collect.Lists;
+
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.schema.SequenceNotFoundException;
+import org.apache.phoenix.schema.TableAlreadyExistsException;
+import org.apache.phoenix.util.PhoenixRuntime;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class TenantIdTypeIT extends BaseHBaseManagedTimeIT {
+
+    private Connection regularConnection(String url) throws SQLException {
+        Properties props = new Properties();
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(nextTimestamp()));
+        return DriverManager.getConnection(url, props);
+    }
+
+    private Connection tenantConnection(String url) throws SQLException {
+        Properties props = new Properties();
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(nextTimestamp()));
+        String tenantIdProperty = this.tenantId.replaceAll("\'", "");
+        props.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, tenantIdProperty);
+        return DriverManager.getConnection(url, props);
+    }
+
+    private Connection inconvertibleConnection(String url) throws SQLException {
+        Properties props = new Properties();
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(nextTimestamp()));
+        String tenantIdProperty = "ABigOlString";
+        props.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, tenantIdProperty);
+        return DriverManager.getConnection(url, props);
+    }
+
+    private final String ddl;
+    private final String dataType;
+    private final String tenantId;
+    private final String otherTenantId;
+    private final String table;
+    private final String view;
+    private final String sequence;
+
+    public TenantIdTypeIT(String dataType, String tenantId, String otherTenantId) {
+        this.dataType = dataType;
+        this.tenantId = tenantId;
+        this.otherTenantId = otherTenantId;
+        String tbl = "foo" + dataType;
+        if(tbl.contains("(")){
+            tbl = tbl.substring(0, tbl.indexOf("("));
+        }
+        this.table = tbl;
+        this.view = tbl + "view";
+        this.sequence = tbl + "sequence";
+        this.ddl = "create table " + table + " (" + "tid "+ dataType + " NOT NULL," + "id INTEGER NOT NULL, \n"
+                + "val VARCHAR " + "CONSTRAINT pk PRIMARY KEY(tid, id)) \n"
+                + "MULTI_TENANT=true";
+    }
+
+    @Parameters
+    public static Collection<Object[]> data() {
+        List<Object[]> testCases = Lists.newArrayList();
+        testCases.add(new Object[] { "INTEGER", "2147483647", "2147483646" });
+        testCases.add(new Object[] { "UNSIGNED_INT", "2147483647", "2147483646" });
+        testCases.add(new Object[] { "BIGINT", "9223372036854775807", "9223372036854775806" });
+        testCases.add(new Object[] { "UNSIGNED_LONG", "9223372036854775807", "9223372036854775806" });
+        testCases.add(new Object[] { "TINYINT", "127", "126" });
+        testCases.add(new Object[] { "UNSIGNED_TINYINT", "85", "84" });
+        testCases.add(new Object[] { "SMALLINT", "32767", "32766" });
+        testCases.add(new Object[] { "UNSIGNED_SMALLINT", "32767", "32766" });
+        testCases.add(new Object[] { "FLOAT", "3.4028234", "3.4028232" });
+        testCases.add(new Object[] { "UNSIGNED_FLOAT", "3.4028234", "3.4028232" });
+        testCases.add(new Object[] { "DOUBLE", "1.7976931348623157", "1.7976931348623156" });
+        testCases.add(new Object[] { "UNSIGNED_DOUBLE", "1.7976931348623157", "1.7976931348623156" });
+        testCases.add(new Object[] { "DECIMAL", "3.402823466", "3.402823465" });
+        testCases.add(new Object[] { "VARCHAR", "\'NameOfTenant\'", "\'Nemesis\'" });
+        testCases.add(new Object[] { "CHAR(10)", "\'1234567890\'", "\'Nemesis\'" });
+
+        return testCases;
+    }
+
+    @Test
+    public void testMultiTenantTables() throws Exception {
+        //Verify we can create the table
+        try (Connection conn = regularConnection(getUrl())) {
+            conn.setAutoCommit(true);
+            conn.createStatement().execute(ddl);
+
+            try {
+                conn.createStatement().execute(ddl);
+                fail("Table with " + dataType + " tenantId not created correctly");
+            } catch (TableAlreadyExistsException e) {
+                // expected
+            }
+        }
+
+        //Insert test data
+        try (Connection conn = regularConnection(getUrl())) {
+            conn.setAutoCommit(true);
+            String query = "upsert into " + table +
+                    " values (" + tenantId + ", 1 , 'valid')";
+
+            conn.createStatement().execute("upsert into " + table +
+                    " values (" + tenantId + ", 1 , 'valid')");
+            conn.createStatement().execute("upsert into " + table +
+                    " values (" + otherTenantId + ", 2 , 'invalid')");
+        }
+
+        //Make sure access is properly restricted and add some tenant-specific schema
+        try (Connection conn = tenantConnection(getUrl())) {
+            conn.setAutoCommit(true);
+            ResultSet rs = conn.createStatement().executeQuery("select * from " + table);
+            assertTrue("Expected 1 row in result set", rs.next());
+            assertEquals("valid", rs.getString(2));
+            assertFalse("Expected 1 row in result set", rs.next());
+
+            try {
+                conn.createStatement()
+                        .executeQuery("select * from " + table + " where tenantId = 2");
+                fail("TenantId column not hidden on multi-tenant connection");
+            } catch (SQLException ex) {
+                assertEquals(SQLExceptionCode.COLUMN_NOT_FOUND.getErrorCode(), ex.getErrorCode());
+            }
+
+            conn.createStatement().execute("create view " + view +
+                    " as select * from " + table);
+
+            conn.createStatement().execute("create sequence " + sequence + " start with 100");
+        }
+
+        //Try inserting data to the view
+        try (Connection conn = tenantConnection(getUrl())) {
+            conn.setAutoCommit(true);
+            conn.createStatement().execute("upsert into " + view +
+                    " values ( next value for " + sequence + ", 'valid')");
+        }
+
+        //Try reading data from the view
+        try (Connection conn = tenantConnection(getUrl())) {
+            ResultSet rs = conn.createStatement().executeQuery("select * from " + view);
+            assertTrue("Expected 2 rows in result set", rs.next());
+            assertEquals("valid", rs.getString(2));
+            assertTrue("Expected 2 rows in result set", rs.next());
+            assertEquals("valid", rs.getString(2));
+            assertFalse("Expected 2 rows in result set", rs.next());
+        }
+
+        //Make sure the tenant-specific schema is specific to that tenant
+        try (Connection conn = regularConnection(getUrl())) {
+            try {
+                conn.createStatement().execute("upsert into " + table +
+                        " values (" + tenantId + ", next value for " + sequence + ", 'valid')");
+                fail();
+            } catch (SequenceNotFoundException ex) {}
+
+            try {
+                ResultSet rs = conn.createStatement().executeQuery("select * from " + view);
+                fail();
+            } catch (SQLException ex) {
+                assertEquals(SQLExceptionCode.TABLE_UNDEFINED.getErrorCode(), ex.getErrorCode());
+            }
+
+        }
+
+        if(dataType != "VARCHAR" && dataType != "CHAR(10)") {
+            //Try setting up an invalid tenant-specific view
+            try (Connection conn = inconvertibleConnection(getUrl())) {
+                conn.setAutoCommit(true);
+                conn.createStatement().execute("create view " + view +
+                        " as select * from " + table);
+            }
+
+            //Try inserting data to the invalid tenant-specific view
+            try (Connection conn = inconvertibleConnection(getUrl())) {
+                conn.setAutoCommit(true);
+                try {
+                    conn.createStatement().execute("upsert into " + view +
+                            " values ( 3 , 'invalid')");
+                    fail();
+                } catch (SQLException ex) {
+                    assertEquals(SQLExceptionCode.TENANTID_IS_OF_WRONG_TYPE.getErrorCode(), ex.getErrorCode());
+                }
+            }
+
+            //Try reading data from the invalid tenant-specific view
+            try (Connection conn = inconvertibleConnection(getUrl())) {
+                try {
+                    ResultSet rs = conn.createStatement().executeQuery("select * from " + view);
+                    fail();
+                } catch (SQLException ex) {
+                    assertEquals(SQLExceptionCode.TENANTID_IS_OF_WRONG_TYPE.getErrorCode(), ex.getErrorCode());
+                }
+            }
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5c048430/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificTablesDDLIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificTablesDDLIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificTablesDDLIT.java
index 05b36c3..327627d 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificTablesDDLIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificTablesDDLIT.java
@@ -217,18 +217,6 @@ public class TenantSpecificTablesDDLIT extends BaseTenantSpecificTablesIT {
     }
     
     @Test
-    public void testBaseTableWrongFormatWithNoTenantTypeId() throws Exception {
-        // tenantId column of wrong type
-        try {
-            createTestTable(getUrl(), "CREATE TABLE BASE_TABLE5 (TENANT_ID INTEGER NOT NULL, ID VARCHAR, A INTEGER CONSTRAINT PK PRIMARY KEY (TENANT_ID, ID)) MULTI_TENANT=true", null, nextTimestamp());
-            fail();
-        }
-        catch (SQLException expected) {
-            assertEquals(SQLExceptionCode.INSUFFICIENT_MULTI_TENANT_COLUMNS.getErrorCode(), expected.getErrorCode());
-        }
-    }
-    
-    @Test
     public void testAddDropColumn() throws Exception {
         Properties props = new Properties();
         props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(nextTimestamp()));

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5c048430/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificViewIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificViewIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificViewIndexIT.java
index e02a473..fc9489d 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificViewIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificViewIndexIT.java
@@ -47,6 +47,11 @@ public class TenantSpecificViewIndexIT extends BaseTenantSpecificViewIndexIT {
     }
 
     @Test
+    public void testUpdatableViewLocalIndexNonStringTenantId() throws Exception {
+        testUpdatableViewNonString(null, true);
+    }
+
+    @Test
     public void testUpdatableViewsWithSameNameDifferentTenants() throws Exception {
         testUpdatableViewsWithSameNameDifferentTenants(null);
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5c048430/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
index a28f614..ebbfd9c 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
@@ -101,8 +101,7 @@ public class DeleteCompiler {
         PName tenantId = connection.getTenantId();
         byte[] tenantIdBytes = null;
         if (tenantId != null) {
-            tenantId = ScanUtil.padTenantIdIfNecessary(table.getRowKeySchema(), table.getBucketNum() != null, tenantId);
-            tenantIdBytes = tenantId.getBytes();
+            tenantIdBytes = ScanUtil.getTenantIdBytes(table.getRowKeySchema(), table.getBucketNum() != null, tenantId);
         }
         final boolean isAutoCommit = connection.getAutoCommit();
         ConnectionQueryServices services = connection.getQueryServices();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5c048430/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
index e12f5a4..08529cc 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
@@ -722,8 +722,7 @@ public class UpsertCompiler {
         final byte[][] values = new byte[nValuesToSet][];
         if (isTenantSpecific) {
             PName tenantId = connection.getTenantId();
-            tenantId = ScanUtil.padTenantIdIfNecessary(table.getRowKeySchema(), table.getBucketNum() != null, tenantId);
-            values[nodeIndex++] = connection.getTenantId().getBytes();
+            values[nodeIndex++] = ScanUtil.getTenantIdBytes(table.getRowKeySchema(), table.getBucketNum() != null, tenantId);
         }
         if (isSharedViewIndex) {
             values[nodeIndex++] = MetaDataUtil.getViewIndexIdDataType().toBytes(table.getViewIndexId());

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5c048430/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
index 601eee1..c575c2e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
@@ -99,21 +99,23 @@ public class WhereOptimizer {
      * @param whereClause the where clause expression
      * @return the new where clause with the key expressions removed
      */
-    public static Expression pushKeyExpressionsToScan(StatementContext context, FilterableStatement statement, Expression whereClause) {
+    public static Expression pushKeyExpressionsToScan(StatementContext context, FilterableStatement statement, Expression whereClause)
+            throws SQLException{
         return pushKeyExpressionsToScan(context, statement, whereClause, null);
     }
 
     // For testing so that the extractedNodes can be verified
     public static Expression pushKeyExpressionsToScan(StatementContext context, FilterableStatement statement,
-            Expression whereClause, Set<Expression> extractNodes) {
+            Expression whereClause, Set<Expression> extractNodes) throws SQLException {
         PName tenantId = context.getConnection().getTenantId();
+        byte[] tenantIdBytes = null;
         PTable table = context.getCurrentTable().getTable();
     	Integer nBuckets = table.getBucketNum();
     	boolean isSalted = nBuckets != null;
     	RowKeySchema schema = table.getRowKeySchema();
     	boolean isMultiTenant = tenantId != null && table.isMultiTenant();
     	if (isMultiTenant) {
-    		tenantId = ScanUtil.padTenantIdIfNecessary(schema, isSalted, tenantId);
+            tenantIdBytes = ScanUtil.getTenantIdBytes(schema, isSalted, tenantId);
     	}
 
         if (whereClause == null && (tenantId == null || !table.isMultiTenant()) && table.getViewIndexId() == null) {
@@ -167,7 +169,7 @@ public class WhereOptimizer {
         boolean hasViewIndex = table.getViewIndexId() != null;
         if (hasMinMaxRange) {
             int minMaxRangeSize = (isSalted ? SaltingUtil.NUM_SALTING_BYTES : 0)
-                    + (isMultiTenant ? tenantId.getBytes().length + 1 : 0) 
+                    + (isMultiTenant ? tenantIdBytes.length + 1 : 0)
                     + (hasViewIndex ? MetaDataUtil.getViewIndexIdDataType().getByteSize() : 0);
             minMaxRangePrefix = new byte[minMaxRangeSize];
         }
@@ -188,7 +190,6 @@ public class WhereOptimizer {
         
         // Add tenant data isolation for tenant-specific tables
         if (isMultiTenant) {
-            byte[] tenantIdBytes = tenantId.getBytes();
             KeyRange tenantIdKeyRange = KeyRange.getKeyRange(tenantIdBytes);
             cnf.add(singletonList(tenantIdKeyRange));
             if (hasMinMaxRange) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5c048430/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java b/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
index acc3c86..59c8e68 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
@@ -235,7 +235,8 @@ public enum SQLExceptionCode {
             
     CANNOT_CREATE_TENANT_SPECIFIC_TABLE(1030, "42Y89", "Cannot create table for tenant-specific connection"),
     DEFAULT_COLUMN_FAMILY_ONLY_ON_CREATE_TABLE(1034, "42Y93", "Default column family may only be specified when creating a table."),
-    INSUFFICIENT_MULTI_TENANT_COLUMNS(1040, "42Y96", "A MULTI_TENANT table must have two or more PK columns with the first column being NOT NULL and of type VARCHAR or CHAR."),
+    INSUFFICIENT_MULTI_TENANT_COLUMNS(1040, "42Y96", "A MULTI_TENANT table must have two or more PK columns with the first column being NOT NULL."),
+    TENANTID_IS_OF_WRONG_TYPE(1041, "42Y97", "The TenantId could not be converted to correct format for this table."),
     VIEW_WHERE_IS_CONSTANT(1045, "43A02", "WHERE clause in VIEW should not evaluate to a constant."),
     CANNOT_UPDATE_VIEW_COLUMN(1046, "43A03", "Column updated in VIEW may not differ from value specified in WHERE clause."),
     TOO_MANY_INDEXES(1047, "43A04", "Too many indexes have already been created on the physical table."),

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5c048430/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
index 11da1c9..af5b25a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
@@ -204,8 +204,18 @@ public abstract class BaseQueryPlan implements QueryPlan {
         } else {
             ScanUtil.setTimeRange(scan, context.getScanTimeRange());
         }
-        
-        ScanUtil.setTenantId(scan, connection.getTenantId() == null ? null : connection.getTenantId().getBytes());
+        byte[] tenantIdBytes;
+        if( table.isMultiTenant() == true ) {
+            tenantIdBytes = connection.getTenantId() == null ? null :
+                    ScanUtil.getTenantIdBytes(
+                            table.getRowKeySchema(),
+                            table.getBucketNum()!=null,
+                            connection.getTenantId());
+        } else {
+            tenantIdBytes = connection.getTenantId() == null ? null : connection.getTenantId().getBytes();
+        }
+
+        ScanUtil.setTenantId(scan, tenantIdBytes);
         String customAnnotations = LogUtil.customAnnotationsToString(connection);
         ScanUtil.setCustomAnnotations(scan, customAnnotations == null ? null : customAnnotations.getBytes());
         // Set local index related scan attributes. 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5c048430/phoenix-core/src/main/java/org/apache/phoenix/execute/MutationState.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/MutationState.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/MutationState.java
index af3bcf3..b723381 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/MutationState.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/MutationState.java
@@ -49,20 +49,9 @@ import org.apache.phoenix.monitoring.MutationMetricQueue.MutationMetric;
 import org.apache.phoenix.monitoring.MutationMetricQueue.NoOpMutationMetricsQueue;
 import org.apache.phoenix.monitoring.ReadMetricQueue;
 import org.apache.phoenix.query.QueryConstants;
-import org.apache.phoenix.schema.IllegalDataException;
-import org.apache.phoenix.schema.MetaDataClient;
-import org.apache.phoenix.schema.PColumn;
-import org.apache.phoenix.schema.PRow;
-import org.apache.phoenix.schema.PTable;
-import org.apache.phoenix.schema.PTableType;
-import org.apache.phoenix.schema.TableRef;
+import org.apache.phoenix.schema.*;
 import org.apache.phoenix.trace.util.Tracing;
-import org.apache.phoenix.util.ByteUtil;
-import org.apache.phoenix.util.IndexUtil;
-import org.apache.phoenix.util.LogUtil;
-import org.apache.phoenix.util.PhoenixRuntime;
-import org.apache.phoenix.util.SQLCloseable;
-import org.apache.phoenix.util.ServerUtil;
+import org.apache.phoenix.util.*;
 import org.apache.htrace.Span;
 import org.apache.htrace.TraceScope;
 import org.slf4j.Logger;
@@ -370,7 +359,7 @@ public class MutationState implements SQLCloseable {
     @SuppressWarnings("deprecation")
     public void commit() throws SQLException {
         int i = 0;
-        byte[] tenantId = connection.getTenantId() == null ? null : connection.getTenantId().getBytes();
+        PName tenantId = connection.getTenantId();
         long[] serverTimeStamps = validate();
         Iterator<Map.Entry<TableRef, Map<ImmutableBytesPtr,RowMutationState>>> iterator = this.mutations.entrySet().iterator();
         // add tracing for this operation
@@ -424,7 +413,11 @@ public class MutationState implements SQLCloseable {
                             // or set the index metadata directly on the Mutation
                             for (Mutation mutation : mutations) {
                                 if (tenantId != null) {
-                                    mutation.setAttribute(PhoenixRuntime.TENANT_ID_ATTRIB, tenantId);
+                                    byte[] tenantIdBytes = ScanUtil.getTenantIdBytes(
+                                        table.getRowKeySchema(),
+                                        table.getBucketNum()!=null,
+                                        tenantId);
+                                    mutation.setAttribute(PhoenixRuntime.TENANT_ID_ATTRIB, tenantIdBytes);
                                 }
                                 mutation.setAttribute(PhoenixIndexCodec.INDEX_UUID, uuidValue);
                                 if (attribValue != null) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5c048430/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
index f74133a..7a7369b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
@@ -1438,7 +1438,7 @@ public class MetaDataClient {
             String tableName = tableNameNode.getTableName();
             String parentTableName = null;
             PName tenantId = connection.getTenantId();
-            String tenantIdStr = tenantId == null ? null : connection.getTenantId().getString();
+            String tenantIdStr = tenantId == null ? null : tenantId.getString();
             Long scn = connection.getSCN();
             long clientTimeStamp = scn == null ? HConstants.LATEST_TIMESTAMP : scn;
             boolean multiTenant = false;
@@ -2032,7 +2032,7 @@ public class MetaDataClient {
         // NOT NULL is a requirement, since otherwise the table key would conflict
         // potentially with the global table definition.
         PColumn tenantIdCol = iterator.next();
-        if (!tenantIdCol.getDataType().isCoercibleTo(PVarchar.INSTANCE) || tenantIdCol.isNullable()) {
+        if ( tenantIdCol.isNullable()) {
             throw new SQLExceptionInfo.Builder(INSUFFICIENT_MULTI_TENANT_COLUMNS).setSchemaName(schemaName).setTableName(tableName).build().buildException();
         }
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5c048430/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
index ae073e2..2a73e25 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
@@ -46,14 +46,16 @@ import org.apache.phoenix.compile.ScanRanges;
 import org.apache.phoenix.compile.StatementContext;
 import org.apache.phoenix.coprocessor.BaseScannerRegionObserver;
 import org.apache.phoenix.coprocessor.MetaDataProtocol;
-import org.apache.phoenix.execute.DescVarLengthFastByteComparisons;
-import org.apache.phoenix.filter.BooleanExpressionFilter;
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.exception.SQLExceptionInfo;
+import org.apache.phoenix.execute.DescVarLengthFastByteComparisons;import org.apache.phoenix.filter.BooleanExpressionFilter;
 import org.apache.phoenix.filter.SkipScanFilter;
 import org.apache.phoenix.query.KeyRange;
 import org.apache.phoenix.query.KeyRange.Bound;
 import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.query.QueryServices;
 import org.apache.phoenix.query.QueryServicesOptions;
+import org.apache.phoenix.schema.IllegalDataException;
 import org.apache.phoenix.schema.PName;
 import org.apache.phoenix.schema.PNameFactory;
 import org.apache.phoenix.schema.RowKeySchema;
@@ -536,7 +538,7 @@ public class ScanUtil {
         while (schema.next(ptr, pos, maxOffset) != null) {
             pos++;
         }
-        Field field = schema.getField(pos-1);
+        Field field = schema.getField(pos - 1);
         if (!field.getDataType().isFixedWidth()) {
             byte[] newLowerRange = new byte[key.length + 1];
             System.arraycopy(key, 0, newLowerRange, 0, key.length);
@@ -688,21 +690,24 @@ public class ScanUtil {
         }
         return Bytes.compareTo(key, 0, nBytesToCheck, ZERO_BYTE_ARRAY, 0, nBytesToCheck) != 0;
     }
-    
-    public static PName padTenantIdIfNecessary(RowKeySchema schema, boolean isSalted, PName tenantId) {
+
+    public static byte[] getTenantIdBytes(RowKeySchema schema, boolean isSalted, PName tenantId)
+            throws SQLException {
         int pkPos = isSalted ? 1 : 0;
-        String tenantIdStr = tenantId.getString();
         Field field = schema.getField(pkPos);
         PDataType dataType = field.getDataType();
-        boolean isFixedWidth = dataType.isFixedWidth();
-        Integer maxLength = field.getMaxLength();
-        if (isFixedWidth && maxLength != null) {
-            if (tenantIdStr.length() < maxLength) {
-                tenantIdStr = (String)dataType.pad(tenantIdStr, maxLength);
-                return PNameFactory.newName(tenantIdStr);
-            }
-        }
-        return tenantId;
+        byte[] convertedValue;
+        try {
+            Object value = dataType.toObject(tenantId.getString());
+            convertedValue = dataType.toBytes(value);
+            ImmutableBytesWritable ptr = new ImmutableBytesWritable(convertedValue);
+            dataType.pad(ptr, field.getMaxLength(), field.getSortOrder());
+            convertedValue = ByteUtil.copyKeyBytesIfNecessary(ptr);
+        } catch(IllegalDataException ex) {
+            throw new SQLExceptionInfo.Builder(SQLExceptionCode.TENANTID_IS_OF_WRONG_TYPE)
+                    .build().buildException();
+        }
+        return convertedValue;
     }
 
     public static Iterator<Filter> getFilterIterator(Scan scan) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5c048430/phoenix-core/src/test/java/org/apache/phoenix/util/TenantIdByteConversionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/util/TenantIdByteConversionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/util/TenantIdByteConversionTest.java
new file mode 100644
index 0000000..4d433aa
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/util/TenantIdByteConversionTest.java
@@ -0,0 +1,294 @@
+/*
+ * 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.phoenix.util;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.fail;
+
+import java.sql.SQLException;
+import org.apache.hadoop.hbase.util.Base64;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.phoenix.schema.*;
+import org.apache.phoenix.schema.types.*;
+import org.apache.phoenix.schema.RowKeySchema.RowKeySchemaBuilder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.collect.Lists;
+import org.mockito.Mockito;
+
+/*Test the getTenantIdBytes method in ScanUtil*/
+@RunWith(Parameterized.class)
+public class TenantIdByteConversionTest {
+
+    private RowKeySchema schema;
+    private boolean isSalted;
+    private PName tenantId;
+    private byte[] expectedTenantIdBytes;
+
+
+    public TenantIdByteConversionTest(
+            RowKeySchema schema,
+            boolean isSalted,
+            PName tenantId,
+            byte[] expectedTenantIdBytes ) {
+        this.schema = schema;
+        this.isSalted = isSalted;
+        this.tenantId = tenantId;
+        this.expectedTenantIdBytes = expectedTenantIdBytes;
+    }
+
+    @Test
+    public void test() {
+        try {
+            byte[] actualTenantIdBytes = ScanUtil.getTenantIdBytes(schema, isSalted, tenantId);
+            assertArrayEquals(expectedTenantIdBytes, actualTenantIdBytes);
+        } catch (SQLException ex) {
+            fail(ex.getMessage());
+        }
+    }
+
+    @Parameters
+    public static Collection<Object[]> data() {
+        List<Object[]> testCases = Lists.newArrayList();
+        // Varchar
+        testCases.add(new Object[] {
+                getDataSchema(PVarchar.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("NameOfTenant"),
+                PVarchar.INSTANCE.toBytes("NameOfTenant")
+        });
+
+        // Char
+        testCases.add(new Object[] {
+                getDataSchema(PChar.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("N"),
+                PChar.INSTANCE.toBytes(PChar.INSTANCE.toObject("N"))
+        });
+
+        //Int
+        testCases.add(new Object[] {
+                getDataSchema(PInteger.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("2147483646"),
+                PInteger.INSTANCE.toBytes(PInteger.INSTANCE.toObject("2147483646"))
+        });
+
+        // UnsignedInt
+        testCases.add(new Object[] {
+                getDataSchema(PUnsignedInt.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("2147483646"),
+                PUnsignedInt.INSTANCE.toBytes(PUnsignedInt.INSTANCE.toObject("2147483646"))
+        });
+
+        //BigInt
+        testCases.add(new Object[] {
+                getDataSchema(PLong.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("9223372036854775806"),
+                PLong.INSTANCE.toBytes(PLong.INSTANCE.toObject("9223372036854775806"))
+        });
+
+        //UnsignedLong
+        testCases.add(new Object[] {
+                getDataSchema(PUnsignedLong.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("9223372036854775806"),
+                PUnsignedLong.INSTANCE.toBytes(PUnsignedLong.INSTANCE.toObject("9223372036854775806"))
+        });
+
+        //TinyInt
+        testCases.add(new Object[] {
+                getDataSchema(PTinyint.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("126"),
+                PTinyint.INSTANCE.toBytes(PTinyint.INSTANCE.toObject("126"))
+        });
+
+        //UnsignedTinyInt
+        testCases.add(new Object[] {
+                getDataSchema(PUnsignedTinyint.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("126"),
+                PUnsignedTinyint.INSTANCE.toBytes(PUnsignedTinyint.INSTANCE.toObject("126"))
+        });
+
+        //SmallInt
+        testCases.add(new Object[] {
+                getDataSchema(PSmallint.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("32766"),
+                PSmallint.INSTANCE.toBytes(PSmallint.INSTANCE.toObject("32766"))
+        });
+
+        //UnsignedSmallInt
+        testCases.add(new Object[] {
+                getDataSchema(PUnsignedSmallint.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("32766"),
+                PUnsignedSmallint.INSTANCE.toBytes(PUnsignedSmallint.INSTANCE.toObject("32766"))
+        });
+
+        //Float
+        testCases.add(new Object[] {
+                getDataSchema(PFloat.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("3.402823466"),
+                PFloat.INSTANCE.toBytes(PFloat.INSTANCE.toObject("3.402823466"))
+        });
+
+        //UnsignedFloat
+        testCases.add(new Object[] {
+                getDataSchema(PUnsignedFloat.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("3.402823466"),
+                PUnsignedFloat.INSTANCE.toBytes(PUnsignedFloat.INSTANCE.toObject("3.402823466"))
+        });
+
+        //Double
+        testCases.add(new Object[] {
+                getDataSchema(PDouble.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("1.7976931348623158"),
+                PDouble.INSTANCE.toBytes(PDouble.INSTANCE.toObject("1.7976931348623158"))
+        });
+
+        //UnsignedDouble
+        testCases.add(new Object[] {
+                getDataSchema(PUnsignedDouble.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("1.7976931348623158"),
+                PUnsignedDouble.INSTANCE.toBytes(PUnsignedDouble.INSTANCE.toObject("1.7976931348623158"))
+        });
+
+        //UnsignedDecimal
+        testCases.add(new Object[] {
+                getDataSchema(PDecimal.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("3.402823466"),
+                PDecimal.INSTANCE.toBytes(PDecimal.INSTANCE.toObject("3.402823466"))
+        });
+
+        //Boolean
+        testCases.add(new Object[] {
+                getDataSchema(PBoolean.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName("true"),
+                PBoolean.INSTANCE.toBytes(PBoolean.INSTANCE.toObject("true"))
+        });
+
+        //Binary
+        byte[] bytes = new byte[] {0, 1, 2, 3};
+        String byteString = new String( Base64.encodeBytes(bytes) );
+        testCases.add(new Object[] {
+                getDataSchema(PBinary.INSTANCE, SortOrder.getDefault()),
+                false,
+                PNameFactory.newName(byteString),
+                PBinary.INSTANCE.toBytes(PBinary.INSTANCE.toObject(byteString))
+        });
+
+        //Descending TenantId
+        testCases.add(new Object[] {
+                getDataSchema(PUnsignedInt.INSTANCE, SortOrder.DESC),
+                false,
+                PNameFactory.newName("2147483646"),
+                PUnsignedInt.INSTANCE.toBytes(PUnsignedInt.INSTANCE.toObject("2147483646"))
+        });
+
+        return testCases;
+    }
+
+    public static RowKeySchema getDataSchema (final PDataType data, final SortOrder sortOrder) {
+        RowKeySchemaBuilder builder = new RowKeySchemaBuilder(3);
+
+        builder.addField(new PDatum() {
+            @Override public boolean isNullable() {
+                return false;
+            }
+
+            @Override public PDataType getDataType() {
+                return data;
+            }
+
+            @Override public Integer getMaxLength() {
+                return 1;
+            }
+
+            @Override public Integer getScale() {
+                return null;
+            }
+
+            @Override public SortOrder getSortOrder() {
+                return sortOrder;
+            }
+        }, false, sortOrder);
+
+        builder.addField(new PDatum() {
+            @Override public boolean isNullable() {
+                return false;
+            }
+
+            @Override public PDataType getDataType() {
+                return PUnsignedInt.INSTANCE;
+            }
+
+            @Override public Integer getMaxLength() {
+                return 3;
+            }
+
+            @Override public Integer getScale() {
+                return null;
+            }
+
+            @Override public SortOrder getSortOrder() {
+                return sortOrder;
+            }
+        }, false, sortOrder);
+
+        builder.addField(new PDatum() {
+            @Override public boolean isNullable() {
+                return true;
+            }
+
+            @Override public PDataType getDataType() {
+                return PVarchar.INSTANCE;
+            }
+
+            @Override public Integer getMaxLength() {
+                return 3;
+            }
+
+            @Override public Integer getScale() {
+                return null;
+            }
+
+            @Override public SortOrder getSortOrder() {
+                return sortOrder;
+            }
+        }, false, sortOrder);
+
+        return builder.build();
+    }
+}


[11/40] phoenix git commit: PHOENIX-2110 Addendum to fix test failure and enforcing tenancy switch check

Posted by ma...@apache.org.
PHOENIX-2110 Addendum to fix test failure and enforcing tenancy switch check


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/f00c777c
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/f00c777c
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/f00c777c

Branch: refs/heads/calcite
Commit: f00c777cf5aa84fc3ecbea041756ba7c8f79aa0d
Parents: 5b46793
Author: Samarth <sa...@salesforce.com>
Authored: Wed Jul 22 15:07:58 2015 -0700
Committer: Samarth <sa...@salesforce.com>
Committed: Wed Jul 22 15:07:58 2015 -0700

----------------------------------------------------------------------
 .../phoenix/end2end/AlterTableWithViewsIT.java  | 31 ++++++++++++
 .../end2end/TenantSpecificTablesDDLIT.java      | 47 +++++++++++++++---
 .../coprocessor/MetaDataEndpointImpl.java       | 50 ++++++++++++++------
 3 files changed, 107 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/f00c777c/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java
index 0399af2..22abd38 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java
@@ -18,6 +18,7 @@
 package org.apache.phoenix.end2end;
 
 import static org.apache.phoenix.exception.SQLExceptionCode.CANNOT_MUTATE_TABLE;
+import static org.apache.phoenix.query.QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT;
 import static org.apache.phoenix.query.QueryConstants.DIVERGED_VIEW_BASE_COLUMN_COUNT;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -1025,6 +1026,36 @@ public class AlterTableWithViewsIT extends BaseHBaseManagedTimeIT {
         }
     }
     
+    @Test
+    public void testAlterSaltedBaseTableWithViews() throws Exception {
+        String baseTable = "testAlterSaltedBaseTableWithViews".toUpperCase();
+        String view1 = "view1".toUpperCase();
+        try (Connection conn = DriverManager.getConnection(getUrl())) {
+            String baseTableDDL = "CREATE TABLE " + baseTable + " (TENANT_ID VARCHAR NOT NULL, PK1 VARCHAR NOT NULL, V1 VARCHAR, V2 VARCHAR, V3 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, PK1)) MULTI_TENANT = true ";
+            conn.createStatement().execute(baseTableDDL);
+
+            try (Connection tenant1Conn = getTenantConnection("tenant1")) {
+                String view1DDL = "CREATE VIEW " + view1 + " ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 CHAR(256)) AS SELECT * FROM " + baseTable;
+                tenant1Conn.createStatement().execute(view1DDL);
+            }
+
+            assertTableDefinition(conn, baseTable, PTableType.TABLE, null, 0, 5, BASE_TABLE_BASE_COLUMN_COUNT, "TENANT_ID", "PK1", "V1", "V2", "V3");
+            assertTableDefinition(conn, view1, PTableType.VIEW, baseTable, 0, 7, 5, "TENANT_ID", "PK1", "V1", "V2", "V3", "VIEW_COL1", "VIEW_COL2");
+
+            String alterBaseTable = "ALTER TABLE " + baseTable + " ADD KV VARCHAR, PK2 VARCHAR PRIMARY KEY";
+            conn.createStatement().execute(alterBaseTable);
+
+            assertTableDefinition(conn, baseTable, PTableType.TABLE, null, 1, 7, BASE_TABLE_BASE_COLUMN_COUNT, "TENANT_ID", "PK1", "V1", "V2", "V3", "KV", "PK2");
+            assertTableDefinition(conn, view1, PTableType.VIEW, baseTable, 1, 9, 7, "TENANT_ID", "PK1", "V1", "V2", "V3", "KV", "PK2", "VIEW_COL1", "VIEW_COL2");
+
+            // verify that the both columns were added to view1
+            try (Connection tenant1Conn = getTenantConnection("tenant1")) {
+                tenant1Conn.createStatement().execute("SELECT KV from " + view1);
+                tenant1Conn.createStatement().execute("SELECT PK2 from " + view1);
+            }
+        }
+    }
+    
     private static long getTableSequenceNumber(PhoenixConnection conn, String tableName) throws SQLException {
         PTable table = conn.getMetaDataCache().getTable(new PTableKey(conn.getTenantId(), SchemaUtil.normalizeIdentifier(tableName)));
         return table.getSequenceNumber();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f00c777c/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificTablesDDLIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificTablesDDLIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificTablesDDLIT.java
index bf86818..05b36c3 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificTablesDDLIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificTablesDDLIT.java
@@ -88,14 +88,49 @@ public class TenantSpecificTablesDDLIT extends BaseTenantSpecificTablesIT {
     }
 
     @Test
-    public void testAlterMultiTenantWithViewsToGlobal() throws Exception {
+    public void testAlteringMultiTenancyForTableWithViewsNotAllowed() throws Exception {
         Properties props = new Properties();
         props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(nextTimestamp()));
-        Connection conn = DriverManager.getConnection(getUrl(), props);
-        try {
-            conn.createStatement().execute("alter table " + PARENT_TABLE_NAME + " set MULTI_TENANT=false");
-        } catch (SQLException e) {
-            assertEquals(SQLExceptionCode.CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+        String multiTenantTable = "BASE_MULTI_TENANT_SWITCH";
+        String globalTable = "GLOBAL_TABLE_SWITCH";
+        // create the two base tables
+        try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+            String ddl = "CREATE TABLE " + multiTenantTable + " (TENANT_ID VARCHAR NOT NULL, PK1 VARCHAR NOT NULL, V1 VARCHAR, V2 VARCHAR, V3 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, PK1)) MULTI_TENANT = true "; 
+            conn.createStatement().execute(ddl);
+            ddl = "CREATE TABLE " + globalTable + " (TENANT_ID VARCHAR NOT NULL, PK1 VARCHAR NOT NULL, V1 VARCHAR, V2 VARCHAR, V3 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, PK1)) ";
+            conn.createStatement().execute(ddl);
+        }
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(nextTimestamp()));
+        props.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, "tenant1");
+        // create view on multi-tenant table
+        try (Connection tenantConn = DriverManager.getConnection(getUrl(), props)) {
+            String viewName = "tenantview";
+            String viewDDL = "CREATE VIEW " + viewName + " AS SELECT * FROM " + multiTenantTable;
+            tenantConn.createStatement().execute(viewDDL);
+        }
+        props = new Properties();
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(nextTimestamp()));
+        // create view on global table
+        try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+            String viewName = "globalView";
+            conn.createStatement().execute("CREATE VIEW " + viewName + " AS SELECT * FROM " + globalTable);
+        }
+        props = new Properties();
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(nextTimestamp()));
+        try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+            try {
+                conn.createStatement().execute("ALTER TABLE " + globalTable + " SET MULTI_TENANT = " + true);
+                fail();
+            } catch (SQLException e) {
+                assertEquals(SQLExceptionCode.CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+            
+            try {
+                conn.createStatement().execute("ALTER TABLE " + multiTenantTable + " SET MULTI_TENANT = " + false);
+                fail();
+            } catch (SQLException e) {
+                assertEquals(SQLExceptionCode.CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
         }
     }
     

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f00c777c/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
index 4c17bf1..13788e1 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
@@ -2240,7 +2240,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
                         TableViewFinderResult childViewsResult = findChildViews(region, tenantId, table, PHYSICAL_TABLE_BYTES);
                         if (childViewsResult.hasViews()) {
                             /* 
-                             * Adding a column is not allowed if
+                             * Dis-allow if:
                              * 1) The meta-data for child view/s spans over
                              * more than one region (since the changes cannot be made in a transactional fashion)
                              * 
@@ -2250,19 +2250,24 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
                              * 3) If the request is from a client that is older than 4.5 version of phoenix. 
                              * Starting from 4.5, metadata requests have the client version included in them. 
                              * We don't want to allow clients before 4.5 to add a column to the base table if it has views.
+                             * 
+                             * 4) Trying to swtich tenancy of a table that has views
                              */
-                             if (!childViewsResult.allViewsInSingleRegion() || table.getBaseColumnCount() == 0 || !request.hasClientVersion()) {
-                                 return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION,
-                                         EnvironmentEdgeManager.currentTimeMillis(), null);
-                             } else {
-                                 mutationsForAddingColumnsToViews = new ArrayList<>(childViewsResult.getResults().size() * tableMetaData.size());
-                                 MetaDataMutationResult mutationResult = addRowsToChildViews(table, tableMetaData, mutationsForAddingColumnsToViews, schemaName, tableName, invalidateList, clientTimeStamp,
-                                         childViewsResult, region, locks);
-                                 // return if we were not able to add the column successfully
-                                 if (mutationResult!=null)
-                                     return mutationResult;
-                             } 
-                         }
+                            if (!childViewsResult.allViewsInSingleRegion() 
+                                    || table.getBaseColumnCount() == 0 
+                                    || !request.hasClientVersion()
+                                    || switchTenancy(table, tableMetaData)) {
+                                return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION,
+                                        EnvironmentEdgeManager.currentTimeMillis(), null);
+                            } else {
+                                mutationsForAddingColumnsToViews = new ArrayList<>(childViewsResult.getResults().size() * tableMetaData.size());
+                                MetaDataMutationResult mutationResult = addRowsToChildViews(table, tableMetaData, mutationsForAddingColumnsToViews, schemaName, tableName, invalidateList, clientTimeStamp,
+                                        childViewsResult, region, locks);
+                                // return if we were not able to add the column successfully
+                                if (mutationResult!=null)
+                                    return mutationResult;
+                            } 
+                        }
                     }
                     for (Mutation m : tableMetaData) {
                         byte[] key = m.getRow();
@@ -2287,7 +2292,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
                                 }
                                 return new MetaDataMutationResult(
                                         MutationCode.COLUMN_ALREADY_EXISTS, EnvironmentEdgeManager
-                                                .currentTimeMillis(), table);
+                                        .currentTimeMillis(), table);
                             } catch (ColumnFamilyNotFoundException e) {
                                 continue;
                             } catch (ColumnNotFoundException e) {
@@ -2301,7 +2306,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
                                         // does not handle this.
                                         return new MetaDataMutationResult(
                                                 MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager
-                                                        .currentTimeMillis(), null);
+                                                .currentTimeMillis(), null);
                                     }
                                     // Add all indexes to invalidate list, as they will all be
                                     // adding the same PK column. No need to lock them, as we
@@ -2327,6 +2332,21 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
                     tableMetaData.addAll(mutationsForAddingColumnsToViews);
                     return null;
                 }
+
+                private boolean switchTenancy(PTable table, List<Mutation> tableMetaData) {
+                    for (Mutation m : tableMetaData) {
+                        if (m instanceof Put) {
+                            Put p = (Put)m;
+                            List<Cell> cells = p.get(TABLE_FAMILY_BYTES, MULTI_TENANT_BYTES);
+                            if (cells != null && cells.size() > 0) {
+                                Cell cell = cells.get(0);
+                                boolean isMutlitenantProp = (boolean)PBoolean.INSTANCE.toObject(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()); 
+                                return table.isMultiTenant() != isMutlitenantProp;
+                            }
+                        }
+                    }
+                    return false;
+                }
             });
             if (result != null) {
                 done.run(MetaDataMutationResult.toProto(result));


[29/40] phoenix git commit: PHOENIX-2171 DOUBLE and FLOAT DESC are stored as ASC

Posted by ma...@apache.org.
PHOENIX-2171 DOUBLE and FLOAT DESC are stored as ASC


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/c435bba8
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/c435bba8
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/c435bba8

Branch: refs/heads/calcite
Commit: c435bba8f375076c47739b757be12f5109bedace
Parents: 5330c07
Author: James Taylor <jt...@salesforce.com>
Authored: Tue Aug 11 01:59:23 2015 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Tue Aug 11 01:59:37 2015 -0700

----------------------------------------------------------------------
 .../org/apache/phoenix/end2end/SortOrderIT.java |  6 ++--
 .../UngroupedAggregateRegionObserver.java       |  6 ++++
 .../org/apache/phoenix/schema/PTableImpl.java   | 10 +++++-
 .../apache/phoenix/schema/types/PDataType.java  |  4 +--
 .../apache/phoenix/schema/types/PDouble.java    | 18 +++++++----
 .../org/apache/phoenix/schema/types/PFloat.java | 18 ++++++-----
 .../org/apache/phoenix/util/UpgradeUtil.java    |  5 +++
 .../phoenix/schema/types/PDataTypeTest.java     | 33 ++++++++++++++++++++
 8 files changed, 82 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/c435bba8/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java
index 9228ab5..fdbd26d 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java
@@ -41,6 +41,8 @@ import org.apache.commons.lang.ArrayUtils;
 import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.types.PDouble;
+import org.apache.phoenix.schema.types.PFloat;
 import org.apache.phoenix.util.PropertiesUtil;
 import org.junit.Assert;
 import org.junit.Test;
@@ -404,7 +406,7 @@ public class SortOrderIT extends BaseHBaseManagedTimeIT {
     public void testNonPKCompare() throws Exception {
         List<Integer> expectedResults = Lists.newArrayList(2,3,4);
         Integer[] saltBuckets = new Integer[] {null,3};
-        PDataType[] dataTypes = new PDataType[] {PDecimal.INSTANCE};
+        PDataType[] dataTypes = new PDataType[] {PDecimal.INSTANCE, PDouble.INSTANCE, PFloat.INSTANCE};
         for (Integer saltBucket : saltBuckets) {
             for (PDataType dataType : dataTypes) {
                 for (SortOrder sortOrder : SortOrder.values()) {
@@ -420,7 +422,7 @@ public class SortOrderIT extends BaseHBaseManagedTimeIT {
         List<Integer> rExpectedResults = new ArrayList<>(expectedResults);
         Collections.reverse(rExpectedResults);
         Integer[] saltBuckets = new Integer[] {null,3};
-        PDataType[] dataTypes = new PDataType[] {PDecimal.INSTANCE};
+        PDataType[] dataTypes = new PDataType[] {PDecimal.INSTANCE, PDouble.INSTANCE, PFloat.INSTANCE};
         for (Integer saltBucket : saltBuckets) {
             for (PDataType dataType : dataTypes) {
                 for (SortOrder sortOrder : SortOrder.values()) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c435bba8/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
index a7e3e44..6b51138 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
@@ -88,6 +88,8 @@ import org.apache.phoenix.schema.tuple.MultiKeyValueTuple;
 import org.apache.phoenix.schema.types.PBinary;
 import org.apache.phoenix.schema.types.PChar;
 import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PDouble;
+import org.apache.phoenix.schema.types.PFloat;
 import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.IndexUtil;
 import org.apache.phoenix.util.KeyValueUtil;
@@ -312,6 +314,10 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver{
                                                 len--;
                                             }
                                             ptr.set(ptr.get(), ptr.getOffset(), len);
+                                        // Special case for re-writing DESC FLOAT and DOUBLE, as they're not inverted like they should be (PHOENIX-2171)
+                                        } else if (field.getDataType() == PFloat.INSTANCE || field.getDataType() == PDouble.INSTANCE) {
+                                            byte[] invertedBytes = SortOrder.invert(ptr.get(), ptr.getOffset(), ptr.getLength());
+                                            ptr.set(invertedBytes);
                                         }
                                     } else if (field.getDataType() == PBinary.INSTANCE) {
                                         // Remove trailing space characters so that the setValues call below will replace them

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c435bba8/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
index 521fb42..8f9bf63 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
@@ -57,6 +57,8 @@ import org.apache.phoenix.schema.stats.PTableStatsImpl;
 import org.apache.phoenix.schema.types.PBinary;
 import org.apache.phoenix.schema.types.PChar;
 import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PDouble;
+import org.apache.phoenix.schema.types.PFloat;
 import org.apache.phoenix.schema.types.PVarchar;
 import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.SchemaUtil;
@@ -407,7 +409,13 @@ public class PTableImpl implements PTable {
         for (PColumn column : allColumns) {
             PName familyName = column.getFamilyName();
             if (familyName == null) {
-                hasColumnsRequiringUpgrade |= (column.getSortOrder() == SortOrder.DESC && (!column.getDataType().isFixedWidth() || column.getDataType() == PChar.INSTANCE || column.getDataType() == PBinary.INSTANCE))
+                hasColumnsRequiringUpgrade |= 
+                        ( column.getSortOrder() == SortOrder.DESC 
+                            && (!column.getDataType().isFixedWidth() 
+                                || column.getDataType() == PChar.INSTANCE 
+                                || column.getDataType() == PFloat.INSTANCE 
+                                || column.getDataType() == PDouble.INSTANCE 
+                                || column.getDataType() == PBinary.INSTANCE) )
                         || (column.getSortOrder() == SortOrder.ASC && column.getDataType() == PBinary.INSTANCE && column.getMaxLength() != null && column.getMaxLength() > 1);
             	pkColumns.add(column);
             }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c435bba8/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
index d79de60..5d8852c 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
@@ -66,16 +66,15 @@ public abstract class PDataType<T> implements DataType<T>, Comparable<PDataType<
         this.ordinal = ordinal;
     }
 
-    @Deprecated
     public static PDataType[] values() {
         return PDataTypeFactory.getInstance().getOrderedTypes();
     }
 
-    @Deprecated
     public int ordinal() {
         return ordinal;
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public Class<T> encodedClass() {
         return getJavaClass();
@@ -942,6 +941,7 @@ public abstract class PDataType<T> implements DataType<T>, Comparable<PDataType<
     public abstract Object toObject(byte[] bytes, int offset, int length, PDataType actualType, SortOrder sortOrder,
             Integer maxLength, Integer scale);
 
+    @SuppressWarnings("unchecked")
     @Override
     public T decode(PositionedByteRange pbr) {
         // default implementation based on existing PDataType methods.

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c435bba8/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDouble.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDouble.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDouble.java
index d11aedf..95a526e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDouble.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDouble.java
@@ -236,15 +236,21 @@ public class PDouble extends PRealNumber<Double> {
     }
 
     @Override
-    public double decodeDouble(byte[] b, int o, SortOrder sortOrder) {
+    public double decodeDouble(byte[] bytes, int o, SortOrder sortOrder) {
       Preconditions.checkNotNull(sortOrder);
-      checkForSufficientLength(b, o, Bytes.SIZEOF_LONG);
+      checkForSufficientLength(bytes, o, Bytes.SIZEOF_LONG);
+      long l;
       if (sortOrder == SortOrder.DESC) {
-        for (int i = o; i < Bytes.SIZEOF_LONG; i++) {
-          b[i] = (byte) (b[i] ^ 0xff);
-        }
+          // Copied from Bytes.toLong(), but without using the toLongUnsafe
+          // TODO: would it be possible to use the toLongUnsafe?
+          l = 0;
+          for(int i = o; i < o + Bytes.SIZEOF_LONG; i++) {
+            l <<= 8;
+            l ^= (bytes[i] ^ 0xff) & 0xFF;
+          }
+      } else {
+          l = Bytes.toLong(bytes, o);
       }
-      long l = Bytes.toLong(b, o);
       l--;
       l ^= (~l >> Long.SIZE - 1) | Long.MIN_VALUE;
       return Double.longBitsToDouble(l);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c435bba8/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloat.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloat.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloat.java
index 67b7d9a..75f8efa 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloat.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloat.java
@@ -243,15 +243,19 @@ public class PFloat extends PRealNumber<Float> {
     public float decodeFloat(byte[] b, int o, SortOrder sortOrder) {
       Preconditions.checkNotNull(sortOrder);
       checkForSufficientLength(b, o, Bytes.SIZEOF_INT);
+      int value;
       if (sortOrder == SortOrder.DESC) {
-        for (int i = o; i < Bytes.SIZEOF_INT; i++) {
-          b[i] = (byte) (b[i] ^ 0xff);
-        }
+          value = 0;
+          for(int i = o; i < (o + Bytes.SIZEOF_INT); i++) {
+            value <<= 8;
+            value ^= (b[i] ^ 0xff) & 0xFF;
+          }
+      } else {
+          value = Bytes.toInt(b, o);
       }
-      int i = Bytes.toInt(b, o);
-      i--;
-      i ^= (~i >> Integer.SIZE - 1) | Integer.MIN_VALUE;
-      return Float.intBitsToFloat(i);
+      value--;
+      value ^= (~value >> Integer.SIZE - 1) | Integer.MIN_VALUE;
+      return Float.intBitsToFloat(value);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c435bba8/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
index 2ab4f8b..c931851 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
@@ -84,6 +84,8 @@ import org.apache.phoenix.schema.types.PBoolean;
 import org.apache.phoenix.schema.types.PChar;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.types.PDouble;
+import org.apache.phoenix.schema.types.PFloat;
 import org.apache.phoenix.schema.types.PInteger;
 import org.apache.phoenix.schema.types.PLong;
 import org.apache.phoenix.schema.types.PVarbinary;
@@ -884,12 +886,15 @@ public class UpgradeUtil {
     // Return all types that are descending and either:
     // 1) variable length, which includes all array types (PHOENIX-2067)
     // 2) fixed length with padding (PHOENIX-2120)
+    // 3) float and double (PHOENIX-2171)
     // We exclude VARBINARY as we no longer support DESC for it.
     private static String getAffectedDataTypes() {
         StringBuilder buf = new StringBuilder("(" 
                 + PVarchar.INSTANCE.getSqlType() + "," +
                 + PChar.INSTANCE.getSqlType() + "," +
                 + PBinary.INSTANCE.getSqlType() + "," +
+                + PFloat.INSTANCE.getSqlType() + "," +
+                + PDouble.INSTANCE.getSqlType() + "," +
                 + PDecimal.INSTANCE.getSqlType() + ","
                 );
         for (PDataType type : PDataType.values()) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c435bba8/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeTest.java b/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeTest.java
index 7ab9093..5657c22 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeTest.java
@@ -41,6 +41,7 @@ import org.apache.phoenix.exception.SQLExceptionCode;
 import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.schema.ConstraintViolationException;
 import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.util.ScanUtil;
 import org.apache.phoenix.util.TestUtil;
 import org.junit.Test;
 
@@ -743,6 +744,38 @@ public class PDataTypeTest {
     }
     
     @Test
+    public void testDoubleComparison() {
+        testRealNumberComparison(PDouble.INSTANCE, new Double[] {0.99, 1.0, 1.001, 1.01, 2.0});
+    }
+    
+    @Test
+    public void testFloatComparison() {
+        testRealNumberComparison(PFloat.INSTANCE, new Float[] {0.99f, 1.0f, 1.001f, 1.01f, 2.0f});
+    }
+    
+    @Test
+    public void testDecimalComparison() {
+        testRealNumberComparison(PDecimal.INSTANCE, new BigDecimal[] {BigDecimal.valueOf(0.99), BigDecimal.valueOf(1.0), BigDecimal.valueOf(1.001), BigDecimal.valueOf(1.01), BigDecimal.valueOf(2.0)});
+    }
+    
+    private static void testRealNumberComparison(PDataType type, Object[] a) {
+        
+        for (SortOrder sortOrder : SortOrder.values()) {
+            int factor = (sortOrder == SortOrder.ASC ? 1 : -1);
+            byte[] prev_b = null;
+            Object prev_o = null;
+            for (Object o : a) {
+                byte[] b = type.toBytes(o, sortOrder);
+                if (prev_b != null) {
+                    assertTrue("Compare of " + o + " with " + prev_o + " " + sortOrder + " failed.", ScanUtil.getComparator(type.isFixedWidth(), sortOrder).compare(prev_b, 0, prev_b.length, b, 0, b.length) * factor < 0);
+                }
+                prev_b = b;
+                prev_o = o;
+            }
+        }
+    }
+    
+    @Test
     public void testDouble() {
         Double na = 0.005;
         byte[] b = PDouble.INSTANCE.toBytes(na);


[26/40] phoenix git commit: PHOENIX-2140 Addendum

Posted by ma...@apache.org.
PHOENIX-2140 Addendum


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/60500f25
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/60500f25
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/60500f25

Branch: refs/heads/calcite
Commit: 60500f25311376c8d62324a04cccede5bf7be955
Parents: caf65ca
Author: Samarth <sa...@salesforce.com>
Authored: Wed Aug 5 10:02:00 2015 -0700
Committer: Samarth <sa...@salesforce.com>
Committed: Wed Aug 5 10:02:00 2015 -0700

----------------------------------------------------------------------
 .../org/apache/phoenix/expression/function/GetBitFunction.java     | 2 +-
 .../org/apache/phoenix/expression/function/SetBitFunction.java     | 2 +-
 .../org/apache/phoenix/expression/function/SetByteFunction.java    | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/60500f25/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetBitFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetBitFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetBitFunction.java
index f26a53d..011841f 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetBitFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/GetBitFunction.java
@@ -37,7 +37,7 @@ import org.apache.phoenix.schema.types.PVarbinary;
         @Argument(allowedTypes = { PInteger.class }) })
 public class GetBitFunction extends PrefixFunction {
 
-    public static final String NAME = “GET_BIT”;
+    public static final String NAME = "GET_BIT";
 
     private Integer offsetPreCompute;
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/60500f25/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetBitFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetBitFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetBitFunction.java
index 3c85c9c..a19ce80 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetBitFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetBitFunction.java
@@ -37,7 +37,7 @@ import org.apache.phoenix.schema.types.PVarbinary;
                 @Argument(allowedTypes = { PInteger.class }) })
 public class SetBitFunction extends ScalarFunction {
 
-    public static final String NAME = “SET_BIT”;
+    public static final String NAME = "SET_BIT";
 
     public SetBitFunction() {
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/60500f25/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetByteFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetByteFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetByteFunction.java
index b32bbcf..e38ee18 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetByteFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SetByteFunction.java
@@ -37,7 +37,7 @@ import org.apache.phoenix.schema.types.PVarbinary;
                 @Argument(allowedTypes = { PInteger.class }) })
 public class SetByteFunction extends ScalarFunction {
 
-    public static final String NAME = “SET_BYTE”;
+    public static final String NAME = "SET_BYTE";
 
     public SetByteFunction() {
     }


[40/40] phoenix git commit: Fix conflicts and bugs after merge

Posted by ma...@apache.org.
Fix conflicts and bugs after merge


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/ab97f1cc
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/ab97f1cc
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/ab97f1cc

Branch: refs/heads/calcite
Commit: ab97f1ccdbe9d74c04a897e98d5ade6e0c9b7dd5
Parents: aa26d84 aa86c89
Author: maryannxue <we...@intel.com>
Authored: Sun Aug 23 13:14:46 2015 -0400
Committer: maryannxue <we...@intel.com>
Committed: Sun Aug 23 13:14:46 2015 -0400

----------------------------------------------------------------------
 dev/make_rc.sh                                  |   59 +-
 phoenix-assembly/pom.xml                        |    2 +-
 phoenix-core/pom.xml                            |    2 +-
 .../apache/phoenix/end2end/AlterTableIT.java    |  929 +--------------
 .../phoenix/end2end/AlterTableWithViewsIT.java  | 1118 ++++++++++++++++++
 .../org/apache/phoenix/end2end/ArrayIT.java     |  201 +++-
 .../org/apache/phoenix/end2end/BaseQueryIT.java |   10 -
 .../end2end/BaseTenantSpecificViewIndexIT.java  |   33 +-
 .../apache/phoenix/end2end/CreateTableIT.java   |   25 +
 .../end2end/GetSetByteBitFunctionEnd2EndIT.java |  100 ++
 .../org/apache/phoenix/end2end/InListIT.java    |   53 +-
 .../phoenix/end2end/LikeExpressionIT.java       |   38 +
 .../apache/phoenix/end2end/LpadFunctionIT.java  |   48 +-
 .../end2end/OctetLengthFunctionEnd2EndIT.java   |   73 ++
 .../apache/phoenix/end2end/RTrimFunctionIT.java |   71 ++
 .../org/apache/phoenix/end2end/SequenceIT.java  |   33 +
 .../org/apache/phoenix/end2end/SortOrderIT.java |  171 ++-
 .../end2end/StringToArrayFunctionIT.java        |  423 +++++++
 .../apache/phoenix/end2end/TenantIdTypeIT.java  |  226 ++++
 .../end2end/TenantSpecificTablesDDLIT.java      |   59 +-
 .../end2end/TenantSpecificViewIndexIT.java      |    5 +
 .../apache/phoenix/mapreduce/IndexToolIT.java   |   42 +-
 .../org/apache/phoenix/rpc/UpdateCacheIT.java   |   17 +
 .../apache/phoenix/calcite/CalciteUtils.java    |   26 +-
 .../phoenix/calcite/rel/PhoenixValues.java      |    4 +-
 .../apache/phoenix/compile/DeleteCompiler.java  |    3 +-
 .../phoenix/compile/ExpressionCompiler.java     |   17 +-
 .../apache/phoenix/compile/HavingCompiler.java  |    2 +-
 .../org/apache/phoenix/compile/KeyPart.java     |    8 +-
 .../phoenix/compile/ListJarsQueryPlan.java      |   17 +
 .../apache/phoenix/compile/QueryCompiler.java   |    4 +-
 .../org/apache/phoenix/compile/ScanRanges.java  |    7 +-
 .../apache/phoenix/compile/UpsertCompiler.java  |    3 +-
 .../apache/phoenix/compile/WhereCompiler.java   |    2 +-
 .../apache/phoenix/compile/WhereOptimizer.java  |  121 +-
 .../coprocessor/MetaDataEndpointImpl.java       |  805 ++++++++-----
 .../UngroupedAggregateRegionObserver.java       |   39 +-
 .../phoenix/exception/SQLExceptionCode.java     |    3 +-
 .../apache/phoenix/execute/BaseQueryPlan.java   |   14 +-
 .../DescVarLengthFastByteComparisons.java       |   12 +
 .../apache/phoenix/execute/HashJoinPlan.java    |    6 +-
 .../execute/LiteralResultIterationPlan.java     |  118 ++
 .../LiteralResultIterationQueryPlan.java        |  118 --
 .../apache/phoenix/execute/MutationState.java   |   23 +-
 .../expression/ArrayConstructorExpression.java  |   28 +-
 .../phoenix/expression/BaseExpression.java      |   43 +-
 .../phoenix/expression/CoerceExpression.java    |   39 +-
 .../expression/ComparisonExpression.java        |   36 +-
 .../phoenix/expression/ExpressionType.java      |   14 +-
 .../phoenix/expression/InListExpression.java    |   26 +-
 .../phoenix/expression/LiteralExpression.java   |   40 +-
 .../expression/function/ArrayFillFunction.java  |   17 +
 .../expression/function/GetBitFunction.java     |   96 ++
 .../expression/function/GetByteFunction.java    |   96 ++
 .../expression/function/InvertFunction.java     |   14 +-
 .../function/OctetLengthFunction.java           |   66 ++
 .../expression/function/PrefixFunction.java     |   37 +-
 .../expression/function/RTrimFunction.java      |   64 +-
 .../function/RoundDateExpression.java           |   12 +-
 .../function/RoundDecimalExpression.java        |   22 +-
 .../expression/function/SetBitFunction.java     |   81 ++
 .../expression/function/SetByteFunction.java    |   81 ++
 .../function/StringToArrayFunction.java         |   91 ++
 .../visitor/CloneExpressionVisitor.java         |    2 +-
 .../apache/phoenix/filter/SkipScanFilter.java   |   13 +-
 .../apache/phoenix/iterate/ExplainTable.java    |    4 +-
 .../phoenix/jdbc/PhoenixDatabaseMetaData.java   |    2 +-
 .../phoenix/mapreduce/index/IndexTool.java      |    6 +-
 .../index/PhoenixIndexImportMapper.java         |    2 +-
 .../util/ColumnInfoToStringEncoderDecoder.java  |   41 +-
 .../util/PhoenixConfigurationUtil.java          |  135 ++-
 .../mapreduce/util/PhoenixMapReduceUtil.java    |    2 +-
 .../phoenix/parse/DeleteJarStatement.java       |   17 +
 .../query/ConnectionQueryServicesImpl.java      |   36 +-
 .../java/org/apache/phoenix/query/KeyRange.java |   42 +-
 .../org/apache/phoenix/query/QueryServices.java |    1 +
 .../phoenix/query/QueryServicesOptions.java     |    4 +-
 .../apache/phoenix/schema/MetaDataClient.java   |    4 +-
 .../org/apache/phoenix/schema/PTableImpl.java   |   33 +-
 .../org/apache/phoenix/schema/Sequence.java     |    3 +-
 .../phoenix/schema/SequenceAllocation.java      |   19 +-
 .../phoenix/schema/types/PArrayDataType.java    |   34 +-
 .../apache/phoenix/schema/types/PBinary.java    |   30 +-
 .../phoenix/schema/types/PBinaryBase.java       |   98 ++
 .../org/apache/phoenix/schema/types/PChar.java  |   11 +
 .../apache/phoenix/schema/types/PDataType.java  |    8 +-
 .../apache/phoenix/schema/types/PDouble.java    |   18 +-
 .../org/apache/phoenix/schema/types/PFloat.java |   18 +-
 .../apache/phoenix/schema/types/PVarbinary.java |    2 +-
 .../phoenix/schema/types/PhoenixArray.java      |    4 -
 .../org/apache/phoenix/util/PhoenixRuntime.java |   49 +-
 .../java/org/apache/phoenix/util/ScanUtil.java  |   97 +-
 .../org/apache/phoenix/util/SchemaUtil.java     |    2 +-
 .../org/apache/phoenix/util/StringUtil.java     |    7 -
 .../org/apache/phoenix/util/UpgradeUtil.java    |  261 ++--
 .../phoenix/compile/WhereOptimizerTest.java     |   53 +-
 .../DescVarLengthFastByteComparisonsTest.java   |   45 +
 .../expression/ArrayToStringFunctionTest.java   |    7 +-
 .../expression/GetSetByteBitFunctionTest.java   |  189 +++
 .../phoenix/expression/NullValueTest.java       |   59 +
 .../expression/OctetLengthFunctionTest.java     |   67 ++
 .../expression/SortOrderExpressionTest.java     |   13 +-
 .../expression/StringToArrayFunctionTest.java   |  275 +++++
 .../hbase/index/write/TestIndexWriter.java      |    2 +-
 .../ColumnInfoToStringEncoderDecoderTest.java   |   42 +-
 .../util/PhoenixConfigurationUtilTest.java      |    5 +-
 .../java/org/apache/phoenix/query/BaseTest.java |   16 +
 .../phoenix/schema/SequenceAllocationTest.java  |   17 +
 .../phoenix/schema/types/PDataTypeTest.java     |   33 +
 .../util/TenantIdByteConversionTest.java        |  294 +++++
 .../java/org/apache/phoenix/util/TestUtil.java  |    5 +-
 phoenix-flume/pom.xml                           |    2 +-
 phoenix-pherf/cluster/pherf.sh                  |    4 +-
 phoenix-pherf/config/env.sh                     |    4 +-
 phoenix-pherf/pom.xml                           |  550 +++------
 .../org/apache/phoenix/pherf/DataIngestIT.java  |   71 +-
 phoenix-pherf/src/main/assembly/cluster.xml     |   11 +-
 .../src/main/assembly/components-minimal.xml    |   33 +
 phoenix-pherf/src/main/assembly/minimal.xml     |   31 +
 phoenix-pherf/src/main/assembly/standalone.xml  |   13 +-
 .../java/org/apache/phoenix/pherf/Pherf.java    |   23 +-
 .../apache/phoenix/pherf/PherfConstants.java    |    5 +
 .../phoenix/pherf/configuration/Scenario.java   |   25 +-
 .../pherf/configuration/XMLConfigParser.java    |   23 +-
 .../apache/phoenix/pherf/util/PhoenixUtil.java  |   86 +-
 .../phoenix/pherf/workload/QueryExecutor.java   |    3 +-
 .../apache/phoenix/pherf/workload/Workload.java |   17 +
 .../phoenix/pherf/workload/WriteWorkload.java   |   64 +-
 .../org/apache/phoenix/pherf/PherfTest.java     |    2 +-
 .../datamodel/test_schema_mt_table.sql          |   31 +
 .../resources/datamodel/test_schema_mt_view.sql |    1 +
 .../test/resources/scenario/test_scenario.xml   |   22 +
 phoenix-pig/pom.xml                             |    2 +-
 .../phoenix/pig/PhoenixHBaseLoaderIT.java       |  136 ++-
 .../phoenix/pig/udf/ReserveNSequenceTestIT.java |   16 +-
 .../apache/phoenix/pig/PhoenixHBaseLoader.java  |    2 +-
 .../apache/phoenix/pig/PhoenixHBaseStorage.java |    3 +-
 .../phoenix/pig/util/PhoenixPigSchemaUtil.java  |   14 +-
 .../org/apache/phoenix/pig/util/TypeUtil.java   |    5 +-
 .../pig/util/PhoenixPigSchemaUtilTest.java      |   30 +-
 phoenix-server-client/pom.xml                   |    2 +-
 phoenix-server/pom.xml                          |    2 +-
 phoenix-spark/pom.xml                           |    2 +-
 .../phoenix/spark/ConfigurationUtil.scala       |   18 +-
 .../phoenix/spark/DataFrameFunctions.scala      |   35 +-
 .../phoenix/spark/PhoenixRecordWritable.scala   |   20 +-
 .../phoenix/spark/ProductRDDFunctions.scala     |   28 +-
 pom.xml                                         |   17 +-
 148 files changed, 6968 insertions(+), 2505 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/ab97f1cc/phoenix-core/pom.xml
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/phoenix/blob/ab97f1cc/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java
----------------------------------------------------------------------
diff --cc phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java
index 3aa2404,0000000..d3666d2
mode 100644,000000..100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java
@@@ -1,824 -1,0 +1,824 @@@
 +package org.apache.phoenix.calcite;
 +
 +import java.sql.SQLException;
 +import java.util.Arrays;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.concurrent.atomic.AtomicInteger;
 +
 +import org.apache.calcite.avatica.util.ByteString;
 +import org.apache.calcite.rex.RexCall;
 +import org.apache.calcite.rex.RexInputRef;
 +import org.apache.calcite.rex.RexLiteral;
 +import org.apache.calcite.rex.RexNode;
 +import org.apache.calcite.sql.SqlAggFunction;
 +import org.apache.calcite.sql.SqlFunction;
 +import org.apache.calcite.sql.SqlKind;
 +import org.apache.calcite.sql.SqlOperator;
 +import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 +import org.apache.calcite.sql.type.SqlTypeName;
 +import org.apache.calcite.util.NlsString;
 +import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
 +import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 +import org.apache.phoenix.calcite.rel.PhoenixRel.Implementor;
 +import org.apache.phoenix.expression.AndExpression;
 +import org.apache.phoenix.expression.CoerceExpression;
 +import org.apache.phoenix.expression.ComparisonExpression;
 +import org.apache.phoenix.expression.DateAddExpression;
 +import org.apache.phoenix.expression.DateSubtractExpression;
 +import org.apache.phoenix.expression.DecimalAddExpression;
 +import org.apache.phoenix.expression.DecimalDivideExpression;
 +import org.apache.phoenix.expression.DecimalMultiplyExpression;
 +import org.apache.phoenix.expression.DecimalSubtractExpression;
 +import org.apache.phoenix.expression.Determinism;
 +import org.apache.phoenix.expression.DoubleAddExpression;
 +import org.apache.phoenix.expression.DoubleDivideExpression;
 +import org.apache.phoenix.expression.DoubleMultiplyExpression;
 +import org.apache.phoenix.expression.DoubleSubtractExpression;
 +import org.apache.phoenix.expression.Expression;
 +import org.apache.phoenix.expression.ExpressionType;
 +import org.apache.phoenix.expression.IsNullExpression;
 +import org.apache.phoenix.expression.LiteralExpression;
 +import org.apache.phoenix.expression.LongAddExpression;
 +import org.apache.phoenix.expression.LongDivideExpression;
 +import org.apache.phoenix.expression.LongMultiplyExpression;
 +import org.apache.phoenix.expression.LongSubtractExpression;
 +import org.apache.phoenix.expression.NotExpression;
 +import org.apache.phoenix.expression.OrExpression;
 +import org.apache.phoenix.expression.StringBasedLikeExpression;
 +import org.apache.phoenix.expression.TimestampAddExpression;
 +import org.apache.phoenix.expression.TimestampSubtractExpression;
 +import org.apache.phoenix.expression.function.AbsFunction;
 +import org.apache.phoenix.expression.function.AggregateFunction;
 +import org.apache.phoenix.expression.function.CeilDateExpression;
 +import org.apache.phoenix.expression.function.CeilDecimalExpression;
 +import org.apache.phoenix.expression.function.CeilTimestampExpression;
 +import org.apache.phoenix.expression.function.CoalesceFunction;
 +import org.apache.phoenix.expression.function.CountAggregateFunction;
 +import org.apache.phoenix.expression.function.CurrentDateFunction;
 +import org.apache.phoenix.expression.function.CurrentTimeFunction;
 +import org.apache.phoenix.expression.function.ExpFunction;
 +import org.apache.phoenix.expression.function.FloorDateExpression;
 +import org.apache.phoenix.expression.function.FloorDecimalExpression;
 +import org.apache.phoenix.expression.function.FunctionExpression;
 +import org.apache.phoenix.expression.function.LnFunction;
 +import org.apache.phoenix.expression.function.LowerFunction;
 +import org.apache.phoenix.expression.function.MaxAggregateFunction;
 +import org.apache.phoenix.expression.function.MinAggregateFunction;
 +import org.apache.phoenix.expression.function.PowerFunction;
 +import org.apache.phoenix.expression.function.RoundDecimalExpression;
 +import org.apache.phoenix.expression.function.RoundTimestampExpression;
 +import org.apache.phoenix.expression.function.SqrtFunction;
 +import org.apache.phoenix.expression.function.TrimFunction;
 +import org.apache.phoenix.expression.function.UpperFunction;
 +import org.apache.phoenix.schema.SortOrder;
 +import org.apache.phoenix.schema.TypeMismatchException;
 +import org.apache.phoenix.schema.types.PDataType;
 +import org.apache.phoenix.schema.types.PDate;
 +import org.apache.phoenix.schema.types.PDecimal;
 +import org.apache.phoenix.schema.types.PDouble;
 +import org.apache.phoenix.schema.types.PLong;
 +import org.apache.phoenix.schema.types.PTimestamp;
 +import org.apache.phoenix.schema.types.PUnsignedTimestamp;
 +
 +import com.google.common.collect.Lists;
 +import com.google.common.collect.Maps;
 +
 +/**
 + * Utilities for interacting with Calcite.
 + */
 +public class CalciteUtils {
 +    private CalciteUtils() {}
 +    
 +    private static AtomicInteger tempAliasCounter = new AtomicInteger(0);
 +  
 +    public static String createTempAlias() {
 +        return "$" + tempAliasCounter.incrementAndGet();
 +    }
 +    
 +    @SuppressWarnings("rawtypes")
 +    public static PDataType sqlTypeNameToPDataType(SqlTypeName sqlTypeName) {
 +        return PDataType.fromTypeId(sqlTypeName.getJdbcOrdinal());
 +    }
 +
 +	private static final Map<SqlKind, ExpressionFactory> EXPRESSION_MAP = Maps
 +			.newHashMapWithExpectedSize(ExpressionType.values().length);
 +	private static final ExpressionFactory getFactory(RexNode node) {
 +		ExpressionFactory eFactory = EXPRESSION_MAP.get(node.getKind());
 +		if (eFactory == null) {
 +			throw new UnsupportedOperationException("Unsupported RexNode: "
 +					+ node);
 +		}
 +		return eFactory;
 +	}
 +	static {
 +        EXPRESSION_MAP.put(SqlKind.AND, new ExpressionFactory() {
 +
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                try {
 +                    return AndExpression.create(convertChildren((RexCall) node, implementor));
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +            
 +        });
 +        EXPRESSION_MAP.put(SqlKind.OR, new ExpressionFactory() {
 +
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                return new OrExpression(convertChildren((RexCall) node, implementor));
 +            }
 +            
 +        });
 +		EXPRESSION_MAP.put(SqlKind.EQUALS, new ExpressionFactory() {
 +
 +			@Override
 +			public Expression newExpression(RexNode node, Implementor implementor) {
 +				ImmutableBytesWritable ptr = new ImmutableBytesWritable();
 +				try {
- 					return ComparisonExpression.create(CompareOp.EQUAL, convertChildren((RexCall) node, implementor), ptr);
++					return ComparisonExpression.create(CompareOp.EQUAL, convertChildren((RexCall) node, implementor), ptr, implementor.getTableRef().getTable().rowKeyOrderOptimizable());
 +				} catch (SQLException e) {
 +					throw new RuntimeException(e);
 +				}
 +			}
 +			
 +		});
 +        EXPRESSION_MAP.put(SqlKind.NOT_EQUALS, new ExpressionFactory() {
 +
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                ImmutableBytesWritable ptr = new ImmutableBytesWritable();
 +                try {
-                     return ComparisonExpression.create(CompareOp.NOT_EQUAL, convertChildren((RexCall) node, implementor), ptr);
++                    return ComparisonExpression.create(CompareOp.NOT_EQUAL, convertChildren((RexCall) node, implementor), ptr, implementor.getTableRef().getTable().rowKeyOrderOptimizable());
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +            
 +        });
 +        EXPRESSION_MAP.put(SqlKind.GREATER_THAN, new ExpressionFactory() {
 +
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                ImmutableBytesWritable ptr = new ImmutableBytesWritable();
 +                try {
-                     return ComparisonExpression.create(CompareOp.GREATER, convertChildren((RexCall) node, implementor), ptr);
++                    return ComparisonExpression.create(CompareOp.GREATER, convertChildren((RexCall) node, implementor), ptr, implementor.getTableRef().getTable().rowKeyOrderOptimizable());
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +            
 +        });
 +        EXPRESSION_MAP.put(SqlKind.GREATER_THAN_OR_EQUAL, new ExpressionFactory() {
 +
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                ImmutableBytesWritable ptr = new ImmutableBytesWritable();
 +                try {
-                     return ComparisonExpression.create(CompareOp.GREATER_OR_EQUAL, convertChildren((RexCall) node, implementor), ptr);
++                    return ComparisonExpression.create(CompareOp.GREATER_OR_EQUAL, convertChildren((RexCall) node, implementor), ptr, implementor.getTableRef().getTable().rowKeyOrderOptimizable());
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +            
 +        });
 +        EXPRESSION_MAP.put(SqlKind.LESS_THAN, new ExpressionFactory() {
 +
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                ImmutableBytesWritable ptr = new ImmutableBytesWritable();
 +                try {
-                     return ComparisonExpression.create(CompareOp.LESS, convertChildren((RexCall) node, implementor), ptr);
++                    return ComparisonExpression.create(CompareOp.LESS, convertChildren((RexCall) node, implementor), ptr, implementor.getTableRef().getTable().rowKeyOrderOptimizable());
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +            
 +        });
 +        EXPRESSION_MAP.put(SqlKind.LESS_THAN_OR_EQUAL, new ExpressionFactory() {
 +
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                ImmutableBytesWritable ptr = new ImmutableBytesWritable();
 +                try {
-                     return ComparisonExpression.create(CompareOp.LESS_OR_EQUAL, convertChildren((RexCall) node, implementor), ptr);
++                    return ComparisonExpression.create(CompareOp.LESS_OR_EQUAL, convertChildren((RexCall) node, implementor), ptr, implementor.getTableRef().getTable().rowKeyOrderOptimizable());
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +            
 +        });
 +        EXPRESSION_MAP.put(SqlKind.PLUS, new ExpressionFactory() {
 +
 +            @SuppressWarnings("rawtypes")
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                try {
 +                    List<Expression> children = convertChildren((RexCall) node, implementor);
 +                    Expression expr = null;
 +                    boolean foundDate = false;
 +                    Determinism determinism = Determinism.ALWAYS;
 +                    PDataType theType = null;
 +                    for(int i = 0; i < children.size(); i++) {
 +                        Expression e = children.get(i);
 +                        determinism = determinism.combine(e.getDeterminism());
 +                        PDataType type = e.getDataType();
 +                        if (type == null) {
 +                            continue; 
 +                        } else if (type.isCoercibleTo(PTimestamp.INSTANCE)) {
 +                            if (foundDate) {
 +                                throw TypeMismatchException.newException(type, node.toString());
 +                            }
 +                            if (theType == null || (theType != PTimestamp.INSTANCE && theType != PUnsignedTimestamp.INSTANCE)) {
 +                                theType = type;
 +                            }
 +                            foundDate = true;
 +                        }else if (type == PDecimal.INSTANCE) {
 +                            if (theType == null || !theType.isCoercibleTo(PTimestamp.INSTANCE)) {
 +                                theType = PDecimal.INSTANCE;
 +                            }
 +                        } else if (type.isCoercibleTo(PLong.INSTANCE)) {
 +                            if (theType == null) {
 +                                theType = PLong.INSTANCE;
 +                            }
 +                        } else if (type.isCoercibleTo(PDouble.INSTANCE)) {
 +                            if (theType == null) {
 +                                theType = PDouble.INSTANCE;
 +                            }
 +                        } else {
 +                            throw TypeMismatchException.newException(type, node.toString());
 +                        }
 +                    }
 +                    if (theType == PDecimal.INSTANCE) {
 +                        expr = new DecimalAddExpression(children);
 +                    } else if (theType == PLong.INSTANCE) {
 +                        expr = new LongAddExpression(children);
 +                    } else if (theType == PDouble.INSTANCE) {
 +                        expr = new DoubleAddExpression(children);
 +                    } else if (theType == null) {
 +                        expr = LiteralExpression.newConstant(null, theType, determinism);
 +                    } else if (theType == PTimestamp.INSTANCE || theType == PUnsignedTimestamp.INSTANCE) {
 +                        expr = new TimestampAddExpression(children);
 +                    } else if (theType.isCoercibleTo(PDate.INSTANCE)) {
 +                        expr = new DateAddExpression(children);
 +                    } else {
 +                        throw TypeMismatchException.newException(theType, node.toString());
 +                    }
 +                    
 +                    PDataType targetType = sqlTypeNameToPDataType(node.getType().getSqlTypeName());
-                     return cast(targetType, expr);
++                    return cast(targetType, expr, implementor);
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +            
 +        });
 +        EXPRESSION_MAP.put(SqlKind.MINUS, new ExpressionFactory() {
 +
 +            @SuppressWarnings("rawtypes")
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                try {
 +                    List<Expression> children = convertChildren((RexCall) node, implementor);
 +                    Expression expr = null;
 +                    int i = 0;
 +                    PDataType theType = null;
 +                    Expression e1 = children.get(0);
 +                    Expression e2 = children.get(1);
 +                    Determinism determinism = e1.getDeterminism().combine(e2.getDeterminism());
 +                    PDataType type1 = e1.getDataType();
 +                    PDataType type2 = e2.getDataType();
 +                    // TODO: simplify this special case for DATE conversion
 +                    /**
 +                     * For date1-date2, we want to coerce to a LONG because this
 +                     * cannot be compared against another date. It has essentially
 +                     * become a number. For date1-5, we want to preserve the DATE
 +                     * type because this can still be compared against another date
 +                     * and cannot be multiplied or divided. Any other time occurs is
 +                     * an error. For example, 5-date1 is an error. The nulls occur if
 +                     * we have bind variables.
 +                     */
 +                    boolean isType1Date = 
 +                            type1 != null 
 +                            && type1 != PTimestamp.INSTANCE
 +                            && type1 != PUnsignedTimestamp.INSTANCE
 +                            && type1.isCoercibleTo(PDate.INSTANCE);
 +                    boolean isType2Date = 
 +                            type2 != null
 +                            && type2 != PTimestamp.INSTANCE
 +                            && type2 != PUnsignedTimestamp.INSTANCE
 +                            && type2.isCoercibleTo(PDate.INSTANCE);
 +                    if (isType1Date || isType2Date) {
 +                        if (isType1Date && isType2Date) {
 +                            i = 2;
 +                            theType = PDecimal.INSTANCE;
 +                        } else if (isType1Date && type2 != null
 +                                && type2.isCoercibleTo(PDecimal.INSTANCE)) {
 +                            i = 2;
 +                            theType = PDate.INSTANCE;
 +                        } else if (type1 == null || type2 == null) {
 +                            /*
 +                             * FIXME: Could be either a Date or BigDecimal, but we
 +                             * don't know if we're comparing to a date or a number
 +                             * which would be disambiguate it.
 +                             */
 +                            i = 2;
 +                            theType = null;
 +                        }
 +                    } else if(type1 == PTimestamp.INSTANCE || type2 == PTimestamp.INSTANCE) {
 +                        i = 2;
 +                        theType = PTimestamp.INSTANCE;
 +                    } else if(type1 == PUnsignedTimestamp.INSTANCE || type2 == PUnsignedTimestamp.INSTANCE) {
 +                        i = 2;
 +                        theType = PUnsignedTimestamp.INSTANCE;
 +                    }
 +                    
 +                    for (; i < children.size(); i++) {
 +                        // This logic finds the common type to which all child types are coercible
 +                        // without losing precision.
 +                        Expression e = children.get(i);
 +                        determinism = determinism.combine(e.getDeterminism());
 +                        PDataType type = e.getDataType();
 +                        if (type == null) {
 +                            continue;
 +                        } else if (type.isCoercibleTo(PLong.INSTANCE)) {
 +                            if (theType == null) {
 +                                theType = PLong.INSTANCE;
 +                            }
 +                        } else if (type == PDecimal.INSTANCE) {
 +                            // Coerce return type to DECIMAL from LONG or DOUBLE if DECIMAL child found,
 +                            // unless we're doing date arithmetic.
 +                            if (theType == null
 +                                    || !theType.isCoercibleTo(PDate.INSTANCE)) {
 +                                theType = PDecimal.INSTANCE;
 +                            }
 +                        } else if (type.isCoercibleTo(PDouble.INSTANCE)) {
 +                            // Coerce return type to DOUBLE from LONG if DOUBLE child found,
 +                            // unless we're doing date arithmetic or we've found another child of type DECIMAL
 +                            if (theType == null
 +                                    || (theType != PDecimal.INSTANCE && !theType.isCoercibleTo(PDate.INSTANCE) )) {
 +                                theType = PDouble.INSTANCE;
 +                            }
 +                        } else {
 +                            throw TypeMismatchException.newException(type, node.toString());
 +                        }
 +                    }
 +                    if (theType == PDecimal.INSTANCE) {
 +                        expr = new DecimalSubtractExpression(children);
 +                    } else if (theType == PLong.INSTANCE) {
 +                        expr = new LongSubtractExpression(children);
 +                    } else if (theType == PDouble.INSTANCE) {
 +                        expr = new DoubleSubtractExpression(children);
 +                    } else if (theType == null) {
 +                        expr = LiteralExpression.newConstant(null, theType, determinism);
 +                    } else if (theType == PTimestamp.INSTANCE || theType == PUnsignedTimestamp.INSTANCE) {
 +                        expr = new TimestampSubtractExpression(children);
 +                    } else if (theType.isCoercibleTo(PDate.INSTANCE)) {
 +                        expr = new DateSubtractExpression(children);
 +                    } else {
 +                        throw TypeMismatchException.newException(theType, node.toString());
 +                    }
 +                    PDataType targetType = sqlTypeNameToPDataType(node.getType().getSqlTypeName());
-                     return cast(targetType, expr);
++                    return cast(targetType, expr, implementor);
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +            
 +        });
 +        EXPRESSION_MAP.put(SqlKind.TIMES, new ExpressionFactory() {
 +
 +            @SuppressWarnings("rawtypes")
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                try {
 +                    List<Expression> children = convertChildren((RexCall) node, implementor);
 +                    Expression expr = null;
 +                    PDataType theType = null;
 +                    Determinism determinism = Determinism.ALWAYS;
 +                    for(int i = 0; i < children.size(); i++) {
 +                        Expression e = children.get(i);
 +                        determinism = determinism.combine(e.getDeterminism());
 +                        PDataType type = e.getDataType();
 +                        if (type == null) {
 +                            continue;
 +                        } else if (type == PDecimal.INSTANCE) {
 +                            theType = PDecimal.INSTANCE;
 +                        } else if (type.isCoercibleTo(PLong.INSTANCE)) {
 +                            if (theType == null) {
 +                                theType = PLong.INSTANCE;
 +                            }
 +                        } else if (type.isCoercibleTo(PDouble.INSTANCE)) {
 +                            if (theType == null) {
 +                                theType = PDouble.INSTANCE;
 +                            }
 +                        } else {
 +                            throw TypeMismatchException.newException(type, node.toString());
 +                        }
 +                    }
 +                    if (theType == PDecimal.INSTANCE) {
 +                        expr = new DecimalMultiplyExpression(children);
 +                    } else if (theType == PLong.INSTANCE) {
 +                        expr = new LongMultiplyExpression(children);
 +                    } else if (theType == PDouble.INSTANCE) {
 +                        expr = new DoubleMultiplyExpression(children);
 +                    } else {
 +                        expr = LiteralExpression.newConstant(null, theType, determinism);
 +                    }
 +                    PDataType targetType = sqlTypeNameToPDataType(node.getType().getSqlTypeName());
-                     return cast(targetType, expr);
++                    return cast(targetType, expr, implementor);
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +            
 +        });
 +        EXPRESSION_MAP.put(SqlKind.DIVIDE, new ExpressionFactory() {
 +
 +            @SuppressWarnings("rawtypes")
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                try {
 +                    List<Expression> children = convertChildren((RexCall) node, implementor);
 +                    Expression expr = null;
 +                    PDataType theType = null;
 +                    Determinism determinism = Determinism.ALWAYS;
 +                    for(int i = 0; i < children.size(); i++) {
 +                        Expression e = children.get(i);
 +                        determinism = determinism.combine(e.getDeterminism());
 +                        PDataType type = e.getDataType();
 +                        if (type == null) {
 +                            continue;
 +                        } else if (type == PDecimal.INSTANCE) {
 +                            theType = PDecimal.INSTANCE;
 +                        } else if (type.isCoercibleTo(PLong.INSTANCE)) {
 +                            if (theType == null) {
 +                                theType = PLong.INSTANCE;
 +                            }
 +                        } else if (type.isCoercibleTo(PDouble.INSTANCE)) {
 +                            if (theType == null) {
 +                                theType = PDouble.INSTANCE;
 +                            }
 +                        } else {
 +                            throw TypeMismatchException.newException(type, node.toString());
 +                        }
 +                    }
 +                    if (theType == PDecimal.INSTANCE) {
 +                        expr = new DecimalDivideExpression( children);
 +                    } else if (theType == PLong.INSTANCE) {
 +                        expr = new LongDivideExpression( children);
 +                    } else if (theType == PDouble.INSTANCE) {
 +                        expr = new DoubleDivideExpression(children);
 +                    } else {
 +                        expr = LiteralExpression.newConstant(null, theType, determinism);
 +                    }
 +                    PDataType targetType = sqlTypeNameToPDataType(node.getType().getSqlTypeName());
-                     return cast(targetType, expr);
++                    return cast(targetType, expr, implementor);
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +            
 +        });
 +		EXPRESSION_MAP.put(SqlKind.LITERAL, new ExpressionFactory() {
 +
 +			@SuppressWarnings("rawtypes")
 +            @Override
 +			public Expression newExpression(RexNode node, Implementor implementor) {
 +				RexLiteral lit = (RexLiteral) node;
 +                PDataType targetType = sqlTypeNameToPDataType(node.getType().getSqlTypeName());
 +				Object o = lit.getValue();
 +				if (o instanceof NlsString) {
 +				    o = ((NlsString) o).getValue();
 +				} else if (o instanceof ByteString) {
 +				    o = ((ByteString) o).getBytes();
 +				}
 +				try {
 +                    return LiteralExpression.newConstant(o, targetType);
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +			}
 +			
 +		});
 +		EXPRESSION_MAP.put(SqlKind.INPUT_REF, new ExpressionFactory() {
 +
 +			@Override
 +			public Expression newExpression(RexNode node, Implementor implementor) {
 +				RexInputRef ref = (RexInputRef) node;
 +				int index = ref.getIndex();
 +				return implementor.newColumnExpression(index);
 +			}
 +			
 +		});
 +		EXPRESSION_MAP.put(SqlKind.CAST, new ExpressionFactory() {
 +
 +            @SuppressWarnings("rawtypes")
 +            @Override
 +            public Expression newExpression(RexNode node,
 +                    Implementor implementor) {                
 +                List<Expression> children = convertChildren((RexCall) node, implementor);
 +                PDataType targetType = sqlTypeNameToPDataType(node.getType().getSqlTypeName());
 +                try {
-                     return cast(targetType, children.get(0));
++                    return cast(targetType, children.get(0), implementor);
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +        });
 +        EXPRESSION_MAP.put(SqlKind.OTHER_FUNCTION, new ExpressionFactory() {
 +            @Override
 +            public Expression newExpression(RexNode node,
 +                    Implementor implementor) {
 +                RexCall call = (RexCall) node;
 +                List<Expression> children = convertChildren(call, implementor);
 +                SqlOperator op = call.getOperator();
 +                try {
 +                    if (op == SqlStdOperatorTable.SQRT) {
 +                        return new SqrtFunction(children);
 +                    } else if (op == SqlStdOperatorTable.POWER) {
 +                        return new PowerFunction(children);
 +                    } else if (op == SqlStdOperatorTable.LN) {
 +                        return new LnFunction(children);
 +                    } else if (op == SqlStdOperatorTable.EXP) {
 +                        return new ExpFunction(children);
 +                    } else if (op == SqlStdOperatorTable.ABS) {
 +                        return new AbsFunction(children);
 +                    } else if (op == SqlStdOperatorTable.CURRENT_DATE) {
 +                        return new CurrentDateFunction();
 +                    } else if (op == SqlStdOperatorTable.CURRENT_TIME) {
 +                        return new CurrentTimeFunction();
 +                    } else if (op == SqlStdOperatorTable.LOWER) {
 +                        return new LowerFunction(children);
 +                    } else if (op == SqlStdOperatorTable.UPPER) {
 +                        return new UpperFunction(children);
 +                    } else if (op == SqlStdOperatorTable.COALESCE) {
 +                        return new CoalesceFunction(children);
 +                    }
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +
 +                throw new UnsupportedOperationException(
 +                        "Unsupported SqlFunction: " + op.getName());
 +            }
 +		});
 +        EXPRESSION_MAP.put(SqlKind.NOT, new ExpressionFactory() {
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                return new NotExpression(convertChildren((RexCall) node, implementor));
 +            }
 +        });
 +        EXPRESSION_MAP.put(SqlKind.IS_TRUE, new ExpressionFactory() {
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                List<Expression> children = convertChildren((RexCall) node, implementor);
 +                return children.get(0);
 +            }
 +        });
 +        EXPRESSION_MAP.put(SqlKind.IS_NOT_TRUE, new ExpressionFactory() {
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                return new NotExpression(convertChildren((RexCall) node, implementor));
 +            }
 +        });
 +        EXPRESSION_MAP.put(SqlKind.IS_FALSE, new ExpressionFactory() {
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                return new NotExpression(convertChildren((RexCall) node, implementor));
 +            }
 +        });
 +        EXPRESSION_MAP.put(SqlKind.IS_NOT_FALSE, new ExpressionFactory() {
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                List<Expression> children = convertChildren((RexCall) node, implementor);
 +                return children.get(0);
 +            }
 +        });
 +        //TODO different kind of LikeExpression based on configuration
 +        EXPRESSION_MAP.put(SqlKind.LIKE, new ExpressionFactory() {
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                List<Expression> children = convertChildren((RexCall) node, implementor);
 +                return new StringBasedLikeExpression(children);
 +            }
 +        });
 +        EXPRESSION_MAP.put(SqlKind.IS_NULL, new ExpressionFactory() {
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                return new IsNullExpression(convertChildren((RexCall) node, implementor), false);
 +            }
 +        });
 +        EXPRESSION_MAP.put(SqlKind.IS_NOT_NULL, new ExpressionFactory() {
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                return new IsNullExpression(convertChildren((RexCall) node, implementor), true);
 +            }
 +        });
 +        EXPRESSION_MAP.put(SqlKind.TRIM, new ExpressionFactory() {
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                //TODO Phoenix only support separate arguments.
 +                try {
 +                    return new TrimFunction(convertChildren((RexCall) node, implementor));
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +        });
 +        EXPRESSION_MAP.put(SqlKind.CEIL, new ExpressionFactory() {
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                //TODO Phoenix only support separate arguments.
 +                List<Expression> children = convertChildren((RexCall) node, implementor);
 +                final Expression firstChild = children.get(0);
 +                final PDataType firstChildDataType = firstChild.getDataType();
 +                try {
 +                    if (firstChildDataType.isCoercibleTo(PDate.INSTANCE)) {
 +                        return CeilDateExpression.create(children);
 +                    } else if (firstChildDataType == PTimestamp.INSTANCE
 +                            || firstChildDataType == PUnsignedTimestamp.INSTANCE) {
 +                        return CeilTimestampExpression.create(children);
 +                    } else if (firstChildDataType.isCoercibleTo(PDecimal.INSTANCE)) {
 +                        return CeilDecimalExpression.create(children);
 +                    } else {
 +                        throw TypeMismatchException.newException(firstChildDataType, "1");
 +                    }
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +        });
 +        EXPRESSION_MAP.put(SqlKind.FLOOR, new ExpressionFactory() {
 +            @Override
 +            public Expression newExpression(RexNode node, Implementor implementor) {
 +                // TODO Phoenix only support separate arguments.
 +                List<Expression> children = convertChildren((RexCall) node, implementor);
 +                final Expression firstChild = children.get(0);
 +                final PDataType firstChildDataType = firstChild.getDataType();
 +                try {
 +                    if (firstChildDataType.isCoercibleTo(PTimestamp.INSTANCE)) {
 +                        return FloorDateExpression.create(children);
 +                    } else if (firstChildDataType.isCoercibleTo(PDecimal.INSTANCE)) {
 +                        return FloorDecimalExpression.create(children);
 +                    } else {
 +                        throw TypeMismatchException.newException(firstChildDataType, "1");
 +                    }
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +        });
 +        // TODO: SqlKind.CASE
 +	}
 +	
 +    private static final Map<String, FunctionFactory> FUNCTION_MAP = Maps
 +            .newHashMapWithExpectedSize(ExpressionType.values().length);
 +    private static final FunctionFactory getFactory(SqlFunction func) {
 +        FunctionFactory fFactory = FUNCTION_MAP.get(func.getName());
 +        if (fFactory == null) {
 +            throw new UnsupportedOperationException("Unsupported SqlFunction: "
 +                    + func);
 +        }
 +        return fFactory;
 +    }
 +    static {
 +        FUNCTION_MAP.put("COUNT", new FunctionFactory() {
 +            @Override
 +            public FunctionExpression newFunction(SqlFunction sqlFunc,
 +                    List<Expression> args) {
 +                if (args.isEmpty()) {
 +                    args = Lists.asList(LiteralExpression.newConstant(1), new Expression[0]);
 +                }
 +                return new CountAggregateFunction(args);
 +            }
 +        });
 +        // TODO Buggy. Disable for now.
 +        //FUNCTION_MAP.put("$SUM0", new FunctionFactory() {
 +        //    @Override
 +        //    public FunctionExpression newFunction(SqlFunction sqlFunc,
 +        //            List<Expression> args) {
 +        //        return new SumAggregateFunction(args);
 +        //    }
 +        //});
 +        FUNCTION_MAP.put("MAX", new FunctionFactory() {
 +            @Override
 +            public FunctionExpression newFunction(SqlFunction sqlFunc,
 +                    List<Expression> args) {
 +                return new MaxAggregateFunction(args, null);
 +            }
 +        });
 +        FUNCTION_MAP.put("MIN", new FunctionFactory() {
 +            @Override
 +            public FunctionExpression newFunction(SqlFunction sqlFunc,
 +                    List<Expression> args) {
 +                return new MinAggregateFunction(args, null);
 +            }
 +        });
 +    }
 +    
 +    private static List<Expression> convertChildren(RexCall call, Implementor implementor) {
 +        List<Expression> children = Lists.newArrayListWithExpectedSize(call.getOperands().size());
 +        for (RexNode op : call.getOperands()) {
 +            Expression child = getFactory(op).newExpression(op, implementor);
 +            children.add(child);
 +        }
 +        return children;
 +    }
 +    
 +    @SuppressWarnings("rawtypes")
-     private static Expression cast(PDataType targetDataType, Expression childExpr) throws SQLException {
++    private static Expression cast(PDataType targetDataType, Expression childExpr, Implementor implementor) throws SQLException {
 +        PDataType fromDataType = childExpr.getDataType();
 +        
 +        Expression expr = childExpr;
 +        if(fromDataType != null) {
 +            expr =  convertToRoundExpressionIfNeeded(fromDataType, targetDataType, childExpr);
 +        }
-         return CoerceExpression.create(expr, targetDataType, SortOrder.getDefault(), expr.getMaxLength());
++        return CoerceExpression.create(expr, targetDataType, SortOrder.getDefault(), expr.getMaxLength(), implementor.getTableRef().getTable().rowKeyOrderOptimizable());
 +    }
 +    
 +    @SuppressWarnings("rawtypes")
 +    private static Expression convertToRoundExpressionIfNeeded(PDataType fromDataType, PDataType targetDataType, Expression expr) throws SQLException {
 +        if(fromDataType == targetDataType) {
 +            return expr;
 +        } else if((fromDataType == PDecimal.INSTANCE || fromDataType == PTimestamp.INSTANCE || fromDataType == PUnsignedTimestamp.INSTANCE) && targetDataType.isCoercibleTo(
 +          PLong.INSTANCE)) {
 +            return RoundDecimalExpression.create(Arrays.asList(expr));
 +        } else if((fromDataType == PDecimal.INSTANCE || fromDataType == PTimestamp.INSTANCE || fromDataType == PUnsignedTimestamp.INSTANCE) && targetDataType.isCoercibleTo(
 +          PDate.INSTANCE)) {
 +            return RoundTimestampExpression.create(Arrays.asList(expr));
 +        } else if(fromDataType.isCastableTo(targetDataType)) {
 +            return expr;
 +        } else {
 +            throw TypeMismatchException.newException(fromDataType, targetDataType, expr.toString());
 +        }
 +    }
 +
 +    public static boolean isExpressionSupported(RexNode node) {
 +        try {
 +            getFactory(node);
 +        } catch (UnsupportedOperationException e) {
 +            return false;
 +        }
 +        if (node instanceof RexCall) {
 +            for (RexNode op : ((RexCall) node).getOperands()) {
 +                if (!isExpressionSupported(op)) {
 +                    return false;
 +                }
 +            }
 +        }
 +        
 +        return true;
 +    }
 +    
 +    public static boolean isAggregateFunctionSupported(SqlAggFunction aggFunc) {
 +        try {
 +            getFactory(aggFunc);
 +        } catch (UnsupportedOperationException e) {
 +            return false;
 +        }
 +
 +        return true;
 +    }
 +
 +	public static Expression toExpression(RexNode node, Implementor implementor) {
 +		ExpressionFactory eFactory = getFactory(node);
 +		Expression expression = eFactory.newExpression(node, implementor);
 +		return expression;
 +	}
 +	
 +	public static AggregateFunction toAggregateFunction(SqlAggFunction aggFunc, List<Integer> args, Implementor implementor) {
 +	    FunctionFactory fFactory = getFactory(aggFunc);
 +	    List<Expression> exprs = Lists.newArrayListWithExpectedSize(args.size());
 +	    for (Integer index : args) {
 +	        exprs.add(implementor.newColumnExpression(index));
 +	    }
 +	    
 +	    return (AggregateFunction) (fFactory.newFunction(aggFunc, exprs));
 +	}
 +	
 +	public static Object evaluateStatelessExpression(RexNode node) {
 +	    try {
 +	        Expression expression = toExpression(node, null);
 +	        if (expression.isStateless() && expression.getDeterminism() == Determinism.ALWAYS) {
 +	            ImmutableBytesWritable ptr = new ImmutableBytesWritable();
 +	            expression.evaluate(null, ptr);
 +	            return expression.getDataType().toObject(ptr);
 +	        }
 +	    } catch (Exception e) {
 +	        // Expression is not stateless. do nothing.
 +	    }
 +	    
 +	    return null;
 +	}
 +	
 +	public static interface ExpressionFactory {
 +		public Expression newExpression(RexNode node, Implementor implementor);
 +	}
 +	
 +	public static interface FunctionFactory {
 +	    public FunctionExpression newFunction(SqlFunction sqlFunc, List<Expression> args);
 +	}
 +}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/ab97f1cc/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixValues.java
----------------------------------------------------------------------
diff --cc phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixValues.java
index 44480b8,0000000..b65b1b8
mode 100644,000000..100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixValues.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixValues.java
@@@ -1,129 -1,0 +1,129 @@@
 +package org.apache.phoenix.calcite.rel;
 +
 +import static org.apache.phoenix.util.PhoenixRuntime.CONNECTIONLESS;
 +import static org.apache.phoenix.util.PhoenixRuntime.JDBC_PROTOCOL;
 +import static org.apache.phoenix.util.PhoenixRuntime.JDBC_PROTOCOL_SEPARATOR;
 +
 +import java.sql.Connection;
 +import java.sql.DriverManager;
 +import java.sql.SQLException;
 +import java.util.Iterator;
 +import java.util.List;
 +
 +import org.apache.calcite.plan.RelOptCluster;
 +import org.apache.calcite.plan.RelOptCost;
 +import org.apache.calcite.plan.RelOptPlanner;
 +import org.apache.calcite.plan.RelTraitSet;
 +import org.apache.calcite.rel.RelCollation;
 +import org.apache.calcite.rel.RelCollationTraitDef;
 +import org.apache.calcite.rel.RelDistribution;
 +import org.apache.calcite.rel.RelDistributionTraitDef;
 +import org.apache.calcite.rel.RelNode;
 +import org.apache.calcite.rel.core.Values;
 +import org.apache.calcite.rel.metadata.RelMdCollation;
 +import org.apache.calcite.rel.metadata.RelMdDistribution;
 +import org.apache.calcite.rel.type.RelDataType;
 +import org.apache.calcite.rex.RexLiteral;
 +import org.apache.hadoop.hbase.KeyValue;
 +import org.apache.hadoop.hbase.client.Scan;
 +import org.apache.phoenix.calcite.CalciteUtils;
 +import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
 +import org.apache.phoenix.compile.ColumnResolver;
 +import org.apache.phoenix.compile.FromCompiler;
 +import org.apache.phoenix.compile.QueryPlan;
 +import org.apache.phoenix.compile.RowProjector;
 +import org.apache.phoenix.compile.SequenceManager;
 +import org.apache.phoenix.compile.StatementContext;
- import org.apache.phoenix.execute.LiteralResultIterationQueryPlan;
++import org.apache.phoenix.execute.LiteralResultIterationPlan;
 +import org.apache.phoenix.execute.TupleProjector;
 +import org.apache.phoenix.expression.Expression;
 +import org.apache.phoenix.jdbc.PhoenixConnection;
 +import org.apache.phoenix.jdbc.PhoenixStatement;
 +import org.apache.phoenix.parse.SelectStatement;
 +import org.apache.phoenix.schema.TableRef;
 +import org.apache.phoenix.schema.tuple.SingleKeyValueTuple;
 +import org.apache.phoenix.schema.tuple.Tuple;
 +
 +import com.google.common.base.Supplier;
 +import com.google.common.collect.ImmutableList;
 +import com.google.common.collect.Lists;
 +
 +/**
 + * Implementation of {@link org.apache.calcite.rel.core.Values}
 + * relational expression in Phoenix.
 + */
 +public class PhoenixValues extends Values implements PhoenixRel {
 +    
 +    private static final PhoenixConnection phoenixConnection;
 +    static {
 +        try {
 +            Class.forName("org.apache.phoenix.jdbc.PhoenixDriver");
 +            final Connection connection =
 +                DriverManager.getConnection(JDBC_PROTOCOL + JDBC_PROTOCOL_SEPARATOR + CONNECTIONLESS);
 +            phoenixConnection =
 +                connection.unwrap(PhoenixConnection.class);
 +        } catch (ClassNotFoundException e) {
 +            throw new RuntimeException(e);
 +        } catch (SQLException e) {
 +            throw new RuntimeException(e);
 +        }
 +    }
 +    
 +    public static PhoenixValues create(RelOptCluster cluster, final RelDataType rowType, final ImmutableList<ImmutableList<RexLiteral>> tuples) {
 +        final RelTraitSet traits =
 +                cluster.traitSetOf(PhoenixRel.CLIENT_CONVENTION)
 +                .replaceIfs(RelCollationTraitDef.INSTANCE,
 +                        new Supplier<List<RelCollation>>() {
 +                    public List<RelCollation> get() {
 +                        return RelMdCollation.values(rowType, tuples);
 +                    }
 +                })
 +                .replaceIf(RelDistributionTraitDef.INSTANCE,
 +                        new Supplier<RelDistribution>() {
 +                    public RelDistribution get() {
 +                        return RelMdDistribution.values(rowType, tuples);
 +                    }
 +                });
 +        return new PhoenixValues(cluster, rowType, tuples, traits);
 +    }
 +    
 +    private PhoenixValues(RelOptCluster cluster, RelDataType rowType, ImmutableList<ImmutableList<RexLiteral>> tuples, RelTraitSet traits) {
 +        super(cluster, rowType, tuples, traits);
 +    }
 +
 +    @Override
 +    public PhoenixValues copy(RelTraitSet traitSet, List<RelNode> inputs) {
 +        assert inputs.isEmpty();
 +        return create(getCluster(), rowType, tuples);
 +    }
 +
 +    @Override
 +    public RelOptCost computeSelfCost(RelOptPlanner planner) {
 +        return super.computeSelfCost(planner).multiplyBy(PHOENIX_FACTOR);
 +    }
 +
 +    @Override
 +    public QueryPlan implement(Implementor implementor) {
 +        List<Tuple> literalResult = Lists.newArrayList();
 +        Iterator<ImmutableList<RexLiteral>> iter = getTuples().iterator();
 +        Tuple baseTuple = new SingleKeyValueTuple(KeyValue.LOWESTKEY);
 +        while (iter.hasNext()) {
 +            ImmutableList<RexLiteral> row = iter.next();
 +            List<Expression> exprs = Lists.newArrayListWithExpectedSize(row.size());
 +            for (RexLiteral rexLiteral : row) {
 +                exprs.add(CalciteUtils.toExpression(rexLiteral, implementor));
 +            }
 +            TupleProjector projector = implementor.project(exprs);
 +            literalResult.add(projector.projectResults(baseTuple));
 +        }
 +        
 +        try {
 +            PhoenixStatement stmt = new PhoenixStatement(phoenixConnection);
 +            ColumnResolver resolver = FromCompiler.getResolver(implementor.getTableRef());
 +            StatementContext context = new StatementContext(stmt, resolver, new Scan(), new SequenceManager(stmt));
-             return new LiteralResultIterationQueryPlan(literalResult.iterator(), context, SelectStatement.SELECT_ONE, TableRef.EMPTY_TABLE_REF, RowProjector.EMPTY_PROJECTOR, null, OrderBy.EMPTY_ORDER_BY, null);
++            return new LiteralResultIterationPlan(literalResult.iterator(), context, SelectStatement.SELECT_ONE, TableRef.EMPTY_TABLE_REF, RowProjector.EMPTY_PROJECTOR, null, OrderBy.EMPTY_ORDER_BY, null);
 +        } catch (SQLException e) {
 +            throw new RuntimeException(e);
 +        }
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/ab97f1cc/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/phoenix/blob/ab97f1cc/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java
----------------------------------------------------------------------
diff --cc phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java
index 16405c0,13963d7..3089b03
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java
@@@ -232,10 -232,10 +232,10 @@@ public class WhereCompiler 
       * @param context the shared context during query compilation
       * @param whereClause the final where clause expression.
       */
 -    private static void setScanFilter(StatementContext context, FilterableStatement statement, Expression whereClause, boolean disambiguateWithFamily, boolean hashJoinOptimization) {
 +    public static void setScanFilter(StatementContext context, FilterableStatement statement, Expression whereClause, boolean disambiguateWithFamily, boolean hashJoinOptimization) {
          Scan scan = context.getScan();
  
-         if (LiteralExpression.isFalse(whereClause)) {
+         if (LiteralExpression.isBooleanFalseOrNull(whereClause)) {
              context.setScanRanges(ScanRanges.NOTHING);
          } else if (whereClause != null && !LiteralExpression.isTrue(whereClause) && !hashJoinOptimization) {
              Filter filter = null;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/ab97f1cc/phoenix-core/src/main/java/org/apache/phoenix/execute/HashJoinPlan.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/phoenix/blob/ab97f1cc/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java
----------------------------------------------------------------------
diff --cc phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java
index 0000000,e7230cc..58c78d2
mode 000000,100644..100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java
@@@ -1,0 -1,108 +1,118 @@@
+ /*
+  * 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.phoenix.execute;
+ 
+ import java.sql.SQLException;
+ import java.util.Collections;
+ import java.util.Iterator;
+ import java.util.List;
+ 
+ import org.apache.hadoop.hbase.KeyValue;
+ import org.apache.hadoop.hbase.client.Scan;
+ import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
+ import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
++import org.apache.phoenix.compile.QueryPlan;
+ import org.apache.phoenix.compile.RowProjector;
+ import org.apache.phoenix.compile.StatementContext;
+ import org.apache.phoenix.iterate.ParallelIteratorFactory;
+ import org.apache.phoenix.iterate.ParallelScanGrouper;
+ import org.apache.phoenix.iterate.ResultIterator;
+ import org.apache.phoenix.iterate.SequenceResultIterator;
+ import org.apache.phoenix.parse.FilterableStatement;
+ import org.apache.phoenix.query.KeyRange;
+ import org.apache.phoenix.schema.TableRef;
+ import org.apache.phoenix.schema.tuple.SingleKeyValueTuple;
+ import org.apache.phoenix.schema.tuple.Tuple;
+ 
+ public class LiteralResultIterationPlan extends BaseQueryPlan {
+     protected final Iterator<Tuple> tupleIterator;
+ 
+     public LiteralResultIterationPlan(StatementContext context, 
+             FilterableStatement statement, TableRef tableRef, RowProjector projection, 
+             Integer limit, OrderBy orderBy, ParallelIteratorFactory parallelIteratorFactory) {
+         this(Collections.<Tuple> singletonList(new SingleKeyValueTuple(KeyValue.LOWESTKEY)).iterator(), 
+                 context, statement, tableRef, projection, limit, orderBy, parallelIteratorFactory);
+     }
+ 
+     public LiteralResultIterationPlan(Iterator<Tuple> tupleIterator, StatementContext context, 
+             FilterableStatement statement, TableRef tableRef, RowProjector projection, 
+             Integer limit, OrderBy orderBy, ParallelIteratorFactory parallelIteratorFactory) {
+         super(context, statement, tableRef, projection, context.getBindManager().getParameterMetaData(), limit, orderBy, GroupBy.EMPTY_GROUP_BY, parallelIteratorFactory);
+         this.tupleIterator = tupleIterator;
+     }
+ 
+     @Override
+     public List<KeyRange> getSplits() {
+         return Collections.emptyList();
+     }
+ 
+     @Override
+     public List<List<Scan>> getScans() {
+         return Collections.emptyList();
+     }
+ 
+     @Override
+     public boolean useRoundRobinIterator() throws SQLException {
+         return false;
+     }
+ 
+     @Override
+     protected ResultIterator newIterator(ParallelScanGrouper scanGrouper)
+             throws SQLException {
+         ResultIterator scanner = new ResultIterator() {
+             private boolean closed = false;
+             private int count = 0;
+ 
+             @Override
+             public void close() throws SQLException {
+                 this.closed = true;;
+             }
+ 
+             @Override
+             public Tuple next() throws SQLException {
+                 if (!this.closed 
+                         && (limit == null || count++ < limit)
+                         && tupleIterator.hasNext()) {
+                     return tupleIterator.next();
+                 }
+                 return null;
+             }
+ 
+             @Override
+             public void explain(List<String> planSteps) {
+             }
+             
+         };
+         
+         if (context.getSequenceManager().getSequenceCount() > 0) {
+             scanner = new SequenceResultIterator(scanner, context.getSequenceManager());
+         }
+         
+         return scanner;
+     }
+ 
++    @Override
++    public QueryPlan limit(Integer limit) {
++        if (limit == this.limit || (limit != null && limit.equals(this.limit)))
++            return this;
++        
++        return new LiteralResultIterationPlan(this.tupleIterator, this.context, this.statement, this.tableRef, 
++                this.projection, limit, this.orderBy, this.parallelIteratorFactory);
++    }
++
+ }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/ab97f1cc/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/phoenix/blob/ab97f1cc/pom.xml
----------------------------------------------------------------------


[21/40] phoenix git commit: PHOENIX-2147 Implement STRING_TO_ARRAY built in function (Dumindu Buddhika)

Posted by ma...@apache.org.
PHOENIX-2147 Implement STRING_TO_ARRAY built in function (Dumindu
Buddhika)


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/265b6dee
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/265b6dee
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/265b6dee

Branch: refs/heads/calcite
Commit: 265b6dee75891c1d4a35cb73d4baaf86cbae1482
Parents: 28a8e97
Author: ramkrishna <ra...@gmail.com>
Authored: Tue Jul 28 10:30:00 2015 +0530
Committer: ramkrishna <ra...@gmail.com>
Committed: Tue Jul 28 10:30:00 2015 +0530

----------------------------------------------------------------------
 .../end2end/StringToArrayFunctionIT.java        | 423 +++++++++++++++++++
 .../phoenix/expression/ExpressionType.java      |   4 +-
 .../function/StringToArrayFunction.java         |  91 ++++
 .../phoenix/schema/types/PArrayDataType.java    |  21 +
 .../expression/StringToArrayFunctionTest.java   | 275 ++++++++++++
 5 files changed, 813 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/265b6dee/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringToArrayFunctionIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringToArrayFunctionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringToArrayFunctionIT.java
new file mode 100644
index 0000000..6e6ac9f
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringToArrayFunctionIT.java
@@ -0,0 +1,423 @@
+/*
+ * 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.phoenix.end2end;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.*;
+
+import org.apache.phoenix.schema.types.PVarchar;
+import org.apache.phoenix.schema.types.PhoenixArray;
+import org.junit.Test;
+
+public class StringToArrayFunctionIT extends BaseHBaseManagedTimeIT {
+
+    private void initTables(Connection conn) throws Exception {
+        String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY, string1 VARCHAR, string2 CHAR(50), delimiter1 VARCHAR, delimiter2 CHAR(20), nullstring1 VARCHAR, nullstring2 CHAR(20))";
+        conn.createStatement().execute(ddl);
+        String dml = "UPSERT INTO regions(region_name, string1, string2, delimiter1, delimiter2, nullstring1, nullstring2) VALUES('SF Bay Area'," +
+                "'a,b,c,d'," +
+                "'1.2.3.4'," +
+                "','," +
+                "'.'," +
+                "'c'," +
+                "'3'" +
+                ")";
+        PreparedStatement stmt = conn.prepareStatement(dml);
+        stmt.execute();
+        conn.commit();
+    }
+
+    @Test
+    public void testStringToArrayFunction1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string1, delimiter1) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", "b", "c", "d"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string1, delimiter1, nullstring1) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", "b", null, "d"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string1, delimiter1, 'a') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{null, "b", "c", "d"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction4() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string1, delimiter1, 'd') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", "b", "c", null});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction5() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string2, delimiter2) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"1", "2", "3", "4"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction6() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string2, delimiter2, nullstring2) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"1", "2", null, "4"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction7() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string2, delimiter2, '1') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{null, "2", "3", "4"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction8() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string2, delimiter2, '4') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"1", "2", "3", null});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction9() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(region_name, ' ', '4') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"SF", "Bay", "Area"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction10() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY('hello,hello,hello', delimiter1) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"hello", "hello", "hello"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction11() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY('a,hello,hello,hello,b', ',', 'hello') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", null, null, null, "b"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction12() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY('b.a.b', delimiter2, 'b') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{null, "a", null});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionWithNestedFunctions1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_LENGTH(STRING_TO_ARRAY('a, b, c', ', ')) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        assertEquals(3, rs.getInt(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionWithNestedFunctions2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(ARRAY_TO_STRING(ARRAY['a', 'b', 'c'], delimiter2), delimiter2, 'b') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", null, "c"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionWithNestedFunctions3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(ARRAY_TO_STRING(ARRAY['a', 'b', 'c'], delimiter2), ARRAY_ELEM(ARRAY[',', '.'], 2), 'b') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", null, "c"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionWithUpsert1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY,varchars VARCHAR[])";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO regions(region_name,varchars) VALUES('SF Bay Area', STRING_TO_ARRAY('hello, world, :-)', ', '))";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT varchars FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"hello", "world", ":-)"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionWithUpsert2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY,varchars VARCHAR[])";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO regions(region_name,varchars) VALUES('SF Bay Area', STRING_TO_ARRAY('a, b, -, c', ', ', '-'))";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT varchars FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", "b", null, "c"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionWithUpsertSelect1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE source (region_name VARCHAR PRIMARY KEY, varchar VARCHAR)";
+        conn.createStatement().execute(ddl);
+
+        ddl = "CREATE TABLE target (region_name VARCHAR PRIMARY KEY, varchars VARCHAR[])";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO source(region_name, varchar) VALUES('SF Bay Area', 'a,b,c,d')";
+        conn.createStatement().execute(dml);
+
+        dml = "UPSERT INTO source(region_name, varchar) VALUES('SF Bay Area2', '1,2,3,4')";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        dml = "UPSERT INTO target(region_name, varchars) SELECT region_name, STRING_TO_ARRAY(varchar, ',') FROM source";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT varchars FROM target");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", "b", "c", "d"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertTrue(rs.next());
+
+        expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"1", "2", "3", "4"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionWithUpsertSelect2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE source (region_name VARCHAR PRIMARY KEY, varchar VARCHAR)";
+        conn.createStatement().execute(ddl);
+
+        ddl = "CREATE TABLE target (region_name VARCHAR PRIMARY KEY, varchars VARCHAR[])";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO source(region_name, varchar) VALUES('SF Bay Area', 'a,b,-,c,d')";
+        conn.createStatement().execute(dml);
+
+        dml = "UPSERT INTO source(region_name, varchar) VALUES('SF Bay Area2', '1,2,-,3,4')";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        dml = "UPSERT INTO target(region_name, varchars) SELECT region_name, STRING_TO_ARRAY(varchar, ',', '-') FROM source";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT varchars FROM target");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", "b", null, "c", "d"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertTrue(rs.next());
+
+        expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"1", "2", null, "3", "4"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionInWhere1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE ARRAY['a', 'b', 'c', 'd']=STRING_TO_ARRAY(string1, delimiter1)");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionInWhere2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE 'a'=ANY(STRING_TO_ARRAY(string1, delimiter1))");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionInWhere3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE 'a'=ALL(STRING_TO_ARRAY('a,a,a,', delimiter1))");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/265b6dee/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
index 3c364c0..9e9cb45 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
@@ -96,6 +96,7 @@ import org.apache.phoenix.expression.function.StddevSampFunction;
 import org.apache.phoenix.expression.function.StringBasedRegexpReplaceFunction;
 import org.apache.phoenix.expression.function.StringBasedRegexpSplitFunction;
 import org.apache.phoenix.expression.function.StringBasedRegexpSubstrFunction;
+import org.apache.phoenix.expression.function.StringToArrayFunction;
 import org.apache.phoenix.expression.function.SubstrFunction;
 import org.apache.phoenix.expression.function.SumAggregateFunction;
 import org.apache.phoenix.expression.function.TimezoneOffsetFunction;
@@ -251,7 +252,8 @@ public enum ExpressionType {
     PowerFunction(PowerFunction.class),
     ArrayConcatFunction(ArrayConcatFunction.class),
     ArrayFillFunction(ArrayFillFunction.class),
-    ArrayToStringFunction(ArrayToStringFunction.class)
+    ArrayToStringFunction(ArrayToStringFunction.class),
+    StringToArrayFunction(StringToArrayFunction.class)
     ;
 
     ExpressionType(Class<? extends Expression> clazz) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/265b6dee/phoenix-core/src/main/java/org/apache/phoenix/expression/function/StringToArrayFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/StringToArrayFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/StringToArrayFunction.java
new file mode 100644
index 0000000..ffbda01
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/StringToArrayFunction.java
@@ -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.phoenix.expression.function;
+
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.*;
+
+@FunctionParseNode.BuiltInFunction(name = StringToArrayFunction.NAME, args = {
+        @FunctionParseNode.Argument(allowedTypes = {PVarchar.class, PChar.class}),
+        @FunctionParseNode.Argument(allowedTypes = {PVarchar.class, PChar.class}),
+        @FunctionParseNode.Argument(allowedTypes = {PVarchar.class, PChar.class}, defaultValue = "null")})
+public class StringToArrayFunction extends ScalarFunction {
+    public static final String NAME = "STRING_TO_ARRAY";
+
+    public StringToArrayFunction() {
+    }
+
+    public StringToArrayFunction(List<Expression> children) {
+        super(children);
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        Expression delimiterExpr = children.get(1);
+        String delimiter;
+        if (!delimiterExpr.evaluate(tuple, ptr)) {
+            return false;
+        } else if (ptr.getLength() == 0) {
+            delimiter = "";
+        } else {
+            delimiter = (String) delimiterExpr.getDataType().toObject(ptr, delimiterExpr.getSortOrder(), delimiterExpr.getMaxLength(), delimiterExpr.getScale());
+        }
+
+        Expression stringExpr = children.get(0);
+        if (!stringExpr.evaluate(tuple, ptr)) {
+            return false;
+        } else if (ptr.getLength() == 0) {
+            return true;
+        }
+        String string = (String) stringExpr.getDataType().toObject(ptr, stringExpr.getSortOrder(), stringExpr.getMaxLength(), stringExpr.getScale());
+
+        Expression nullExpr = children.get(2);
+        String nullString = null;
+        if (nullExpr.evaluate(tuple, ptr) && ptr.getLength() != 0) {
+            nullString = (String) nullExpr.getDataType().toObject(ptr, nullExpr.getSortOrder(), nullExpr.getMaxLength(), nullExpr.getScale());
+        }
+
+        return PArrayDataType.stringToArray(ptr, string, delimiter, nullString, getSortOrder());
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public Integer getMaxLength() {
+        return null;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PVarcharArray.INSTANCE;
+    }
+
+    @Override
+    public SortOrder getSortOrder() {
+        return children.get(0).getSortOrder();
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/265b6dee/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
index 28144fd..a1759a4 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
@@ -24,6 +24,7 @@ import java.sql.Types;
 import java.text.Format;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.regex.Pattern;
 
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.hadoop.hbase.util.Bytes;
@@ -990,6 +991,26 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
         return true;
     }
 
+    public static boolean stringToArray(ImmutableBytesWritable ptr, String string, String delimiter, String nullString, SortOrder sortOrder) {
+        Pattern pattern = Pattern.compile(Pattern.quote(delimiter));
+        String[] array;
+        if (delimiter.length() != 0) {
+            array = pattern.split(string);
+            if (nullString != null) {
+                for (int i = 0; i < array.length; i++) {
+                    if (array[i].equals(nullString)) {
+                        array[i] = null;
+                    }
+                }
+            }
+        } else {
+            array = string.split("(?!^)");
+        }
+        PhoenixArray phoenixArray = new PhoenixArray(PVarchar.INSTANCE, array);
+        ptr.set(PVarcharArray.INSTANCE.toBytes(phoenixArray, PVarchar.INSTANCE, sortOrder));
+        return true;
+    }
+
     public static int serailizeOffsetArrayIntoStream(DataOutputStream oStream, TrustedByteArrayOutputStream byteStream,
             int noOfElements, int maxOffset, int[] offsetPos) throws IOException {
         int offsetPosition = (byteStream.size());

http://git-wip-us.apache.org/repos/asf/phoenix/blob/265b6dee/phoenix-core/src/test/java/org/apache/phoenix/expression/StringToArrayFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/StringToArrayFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/StringToArrayFunctionTest.java
new file mode 100644
index 0000000..6e8e532
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/StringToArrayFunctionTest.java
@@ -0,0 +1,275 @@
+/*
+ * 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.phoenix.expression;
+
+import static org.junit.Assert.assertEquals;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.function.StringToArrayFunction;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.types.*;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class StringToArrayFunctionTest {
+
+    private static void testExpression(LiteralExpression array, LiteralExpression delimiter, LiteralExpression nullString, PhoenixArray expected)
+            throws SQLException {
+        List<Expression> expressions = Lists.newArrayList((Expression) array);
+        expressions.add(delimiter);
+        expressions.add(nullString);
+
+        Expression stringToArrayFunction = new StringToArrayFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        stringToArrayFunction.evaluate(null, ptr);
+        PhoenixArray result = (PhoenixArray) stringToArrayFunction.getDataType().toObject(ptr, stringToArrayFunction.getSortOrder(), stringToArrayFunction.getMaxLength(), stringToArrayFunction.getScale());
+        assertEquals(expected, result);
+    }
+
+    private static void test(String string, String delimiter, String nullString, PhoenixArray expected, SortOrder stringSortOrder, SortOrder delimiterSortOrder, SortOrder nullStringSortOrder, PDataType stringType, PDataType delimiterType, PDataType nullStringType) throws SQLException {
+        LiteralExpression arrayLiteral, delimiterLiteral, nullStringLiteral;
+        arrayLiteral = LiteralExpression.newConstant(string, stringType, null, null, stringSortOrder, Determinism.ALWAYS);
+        delimiterLiteral = LiteralExpression.newConstant(delimiter, delimiterType, null, null, delimiterSortOrder, Determinism.ALWAYS);
+        nullStringLiteral = LiteralExpression.newConstant(nullString, nullStringType, null, null, nullStringSortOrder, Determinism.ALWAYS);
+        testExpression(arrayLiteral, delimiterLiteral, nullStringLiteral, expected);
+    }
+
+    @Test
+    public void testStringToArrayFunction1() throws SQLException {
+        String string = "1,2,3,4,5";
+        Object[] o1 = new Object[]{"1", "2", "3", "4", "5"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = ",";
+        String nullString = "*";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction2() throws SQLException {
+        String string = "1,2,3,4,5";
+        Object[] o1 = new Object[]{"1", "2", "3", "4", "5"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = ",";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction3() throws SQLException {
+        String string = "1234";
+        Object[] o1 = new Object[]{"1", "2", "3", "4"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = null;
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction4() throws SQLException {
+        String string = "1";
+        Object[] o1 = new Object[]{"1"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = ",";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction5() throws SQLException {
+        String string = "hello, hello, hello";
+        Object[] o1 = new Object[]{"hello", "hello", "hello"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = ", ";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction6() throws SQLException {
+        String string = "1.2...2.3...5.6";
+        Object[] o1 = new Object[]{"1.2", "2.3", "5.6"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = "...";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction7() throws SQLException {
+        String string = "a\\b\\c\\d\\e\\f";
+        Object[] o1 = new Object[]{"a", "b", "c", "d", "e", "f"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = "\\";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction8() throws SQLException {
+        String string = "a-b-c-d-e-f-";
+        Object[] o1 = new Object[]{"a", "b", "c", "d", "e", "f"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = "-";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction9() throws SQLException {
+        String string = "a b c d e f";
+        Object[] o1 = new Object[]{"a", "b", "c", "d", "e", "f"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = " ";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction10() throws SQLException {
+        String string = "axbxcxdxexf";
+        Object[] o1 = new Object[]{"a", "b", "c", "d", "e", "f"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = "x";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction11() throws SQLException {
+        String string = "axbxcxdxexfx*";
+        Object[] o1 = new Object[]{"a", "b", "c", "d", "e", "f", null};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = "x";
+        String nullString = "*";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction12() throws SQLException {
+        String string = "* a b c d e f";
+        Object[] o1 = new Object[]{null, "a", "b", "c", "d", "e", "f"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = " ";
+        String nullString = "*";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction13() throws SQLException {
+        String string = "a * b * c d e f";
+        Object[] o1 = new Object[]{"a", null, "b", null, "c", "d", "e", "f"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = " ";
+        String nullString = "*";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction14() throws SQLException {
+        String string = "null a null";
+        Object[] o1 = new Object[]{null, "a", null};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = " ";
+        String nullString = "null";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction16() throws SQLException {
+        String string = "null a null";
+        Object[] o1 = new Object[]{null, "a", null};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = " ";
+        String nullString = "null";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction17() throws SQLException {
+        String string = "null a null";
+        Object[] o1 = new Object[]{null, "a", null};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = " ";
+        String nullString = "null";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction18() throws SQLException {
+        String string = "null,a,null";
+        Object[] o1 = new Object[]{null, "a", null};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = ",";
+        String nullString = "null";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PChar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PChar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction19() throws SQLException {
+        String string = "null,a,null";
+        Object[] o1 = new Object[]{null, "a", null};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = ",";
+        String nullString = "null";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PChar.INSTANCE, PChar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PChar.INSTANCE, PChar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction20() throws SQLException {
+        String string = "abc";
+        Object[] o1 = new Object[]{"a", "b", "c"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = null;
+        String nullString = "null";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PChar.INSTANCE, PChar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PChar.INSTANCE, PChar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction21() throws SQLException {
+        String string = "(?!^)";
+        Object[] o1 = new Object[]{"(", "?", "!", "^", ")"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = null;
+        String nullString = null;
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+}


[32/40] phoenix git commit: PHOENIX-2175 Bump calcite version to 1.3.0-incubating

Posted by ma...@apache.org.
PHOENIX-2175 Bump calcite version to 1.3.0-incubating


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/209b45e9
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/209b45e9
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/209b45e9

Branch: refs/heads/calcite
Commit: 209b45e912e8e7202583788f541dc8cd299f7e27
Parents: 274eb42
Author: Nick Dimiduk <nd...@apache.org>
Authored: Wed Aug 12 15:33:18 2015 -0700
Committer: Nick Dimiduk <nd...@apache.org>
Committed: Wed Aug 12 15:39:24 2015 -0700

----------------------------------------------------------------------
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/209b45e9/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index bda6628..703831a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -109,7 +109,7 @@
     <collections.version>3.2.1</collections.version>
     <jodatime.version>2.7</jodatime.version>
     <joni.version>2.1.2</joni.version>
-    <calcite.version>1.2.0-incubating</calcite.version>
+    <calcite.version>1.3.0-incubating</calcite.version>
 
     <!-- Test Dependencies -->
     <mockito-all.version>1.8.5</mockito-all.version>


[12/40] phoenix git commit: PHOENIX-2139 LIKE '%' is not filtering out null columns

Posted by ma...@apache.org.
PHOENIX-2139 LIKE '%' is not filtering out null columns


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/a50ead27
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/a50ead27
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/a50ead27

Branch: refs/heads/calcite
Commit: a50ead27afa467f6d530052354ac741fb8aa1307
Parents: f00c777
Author: James Taylor <ja...@apache.org>
Authored: Wed Jul 22 16:12:15 2015 -0700
Committer: James Taylor <ja...@apache.org>
Committed: Wed Jul 22 16:13:17 2015 -0700

----------------------------------------------------------------------
 .../phoenix/end2end/LikeExpressionIT.java       | 38 ++++++++++++++++++++
 .../phoenix/compile/ExpressionCompiler.java     |  2 ++
 2 files changed, 40 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/a50ead27/phoenix-core/src/it/java/org/apache/phoenix/end2end/LikeExpressionIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/LikeExpressionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/LikeExpressionIT.java
index 1ee0669..1d93341 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/LikeExpressionIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/LikeExpressionIT.java
@@ -85,4 +85,42 @@ public class LikeExpressionIT extends BaseHBaseManagedTimeIT {
         testLikeExpression(conn, "%A%", 3, 42);
         conn.close();
     }
+
+    @Test
+    public void testLikeEverythingExpression() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        String ddl = "CREATE TABLE t (k1 VARCHAR, k2 VARCHAR, CONSTRAINT pk PRIMARY KEY (k1,k2))";
+        conn.createStatement().execute(ddl);
+        conn.createStatement().execute("UPSERT INTO t VALUES('aa','bb')");
+        conn.createStatement().execute("UPSERT INTO t VALUES('ab','bc')");
+        conn.createStatement().execute("UPSERT INTO t VALUES(null,'cc')");
+        conn.createStatement().execute("UPSERT INTO t VALUES('dd',null)");
+        conn.commit();
+        
+        ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM t WHERE k1 LIKE '%'");
+        assertTrue(rs.next());
+        assertEquals("aa", rs.getString(1));
+        assertEquals("bb", rs.getString(2));
+        assertTrue(rs.next());
+        assertEquals("ab", rs.getString(1));
+        assertEquals("bc", rs.getString(2));
+        assertTrue(rs.next());
+        assertEquals("dd", rs.getString(1));
+        assertEquals(null, rs.getString(2));
+        assertFalse(rs.next());
+        
+        rs = conn.createStatement().executeQuery("SELECT * FROM t WHERE k2 LIKE '%'");
+        assertTrue(rs.next());
+        assertEquals(null, rs.getString(1));
+        assertEquals("cc", rs.getString(2));
+        assertTrue(rs.next());
+        assertEquals("aa", rs.getString(1));
+        assertEquals("bb", rs.getString(2));
+        assertTrue(rs.next());
+        assertEquals("ab", rs.getString(1));
+        assertEquals("bc", rs.getString(2));
+        assertFalse(rs.next());
+        
+        conn.close();
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/a50ead27/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
index 2f786ec..1278494 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
@@ -513,6 +513,8 @@ public class ExpressionCompiler extends UnsupportedAllParseNodeVisitor<Expressio
                       return new ComparisonExpression(Arrays.asList(lhs,rhs), op);
                   }
                 }
+            } else if (index == 0 && pattern.length() == 1) {
+                return IsNullExpression.create(lhs, true, context.getTempPtr());
             }
         }
         QueryServices services = context.getConnection().getQueryServices();


[09/40] phoenix git commit: PHOENIX-2110 Primary key changes should be pushed to diverged views

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/5b46793b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java
new file mode 100644
index 0000000..0399af2
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java
@@ -0,0 +1,1047 @@
+/*
+ * 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.phoenix.end2end;
+
+import static org.apache.phoenix.exception.SQLExceptionCode.CANNOT_MUTATE_TABLE;
+import static org.apache.phoenix.query.QueryConstants.DIVERGED_VIEW_BASE_COLUMN_COUNT;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.phoenix.compile.QueryPlan;
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
+import org.apache.phoenix.jdbc.PhoenixStatement;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.schema.PColumn;
+import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.PTableKey;
+import org.apache.phoenix.schema.PTableType;
+import org.apache.phoenix.util.IndexUtil;
+import org.apache.phoenix.util.PhoenixRuntime;
+import org.apache.phoenix.util.SchemaUtil;
+import org.junit.Test;
+
+import com.google.common.base.Objects;
+
+public class AlterTableWithViewsIT extends BaseHBaseManagedTimeIT {
+    
+    @Test
+    public void testAddNewColumnsToBaseTableWithViews() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        try {       
+            conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
+                    + " ID char(1) NOT NULL,"
+                    + " COL1 integer NOT NULL,"
+                    + " COL2 bigint NOT NULL,"
+                    + " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
+                    + " )");
+            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
+            
+            conn.createStatement().execute("CREATE VIEW VIEWOFTABLE ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR ) AS SELECT * FROM TABLEWITHVIEW");
+            assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+            
+            // adding a new pk column and a new regular column
+            conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD COL3 varchar(10) PRIMARY KEY, COL4 integer");
+            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 5, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2", "COL3", "COL4");
+            assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 7, 5, "ID", "COL1", "COL2", "COL3", "COL4", "VIEW_COL1", "VIEW_COL2");
+        } finally {
+            conn.close();
+        }
+    }
+    
+    @Test
+    public void testAddExistingViewColumnToBaseTableWithViews() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        try {       
+            conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
+                    + " ID char(10) NOT NULL,"
+                    + " COL1 integer NOT NULL,"
+                    + " COL2 bigint NOT NULL,"
+                    + " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
+                    + " )");
+            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
+            
+            conn.createStatement().execute("CREATE VIEW VIEWOFTABLE ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256), VIEW_COL3 VARCHAR, VIEW_COL4 DECIMAL, VIEW_COL5 DECIMAL(10,2), VIEW_COL6 VARCHAR, CONSTRAINT pk PRIMARY KEY (VIEW_COL5, VIEW_COL6) ) AS SELECT * FROM TABLEWITHVIEW");
+            assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 9, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2", "VIEW_COL3", "VIEW_COL4", "VIEW_COL5", "VIEW_COL6");
+            
+            // upsert single row into view
+            String dml = "UPSERT INTO VIEWOFTABLE VALUES(?,?,?,?,?, ?, ?, ?, ?)";
+            PreparedStatement stmt = conn.prepareStatement(dml);
+            stmt.setString(1, "view1");
+            stmt.setInt(2, 12);
+            stmt.setInt(3, 13);
+            stmt.setInt(4, 14);
+            stmt.setString(5, "view5");
+            stmt.setString(6, "view6");
+            stmt.setInt(7, 17);
+            stmt.setInt(8, 18);
+            stmt.setString(9, "view9");
+            stmt.execute();
+            conn.commit();
+            
+            try {
+                // should fail because there is already a view column with same name of different type
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 char(10)");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }           
+            
+            try {
+                // should fail because there is already a view column with same name with different scale
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,1)");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            } 
+            
+            try {
+                // should fail because there is already a view column with same name with different length
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(9,2)");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            } 
+            
+            try {
+                // should fail because there is already a view column with different length
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+            
+            // validate that there were no columns added to the table or view
+            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
+            assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 9, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2", "VIEW_COL3", "VIEW_COL4", "VIEW_COL5", "VIEW_COL6");
+            
+            // should succeed 
+            conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL4 DECIMAL, VIEW_COL2 VARCHAR(256)");
+            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 5, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2", "VIEW_COL4", "VIEW_COL2");
+            assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 9, 5, "ID", "COL1", "COL2", "VIEW_COL4", "VIEW_COL2", "VIEW_COL1", "VIEW_COL3", "VIEW_COL5", "VIEW_COL6");
+            
+            // query table
+            ResultSet rs = stmt.executeQuery("SELECT * FROM TABLEWITHVIEW");
+            assertTrue(rs.next());
+            assertEquals("view1", rs.getString("ID"));
+            assertEquals(12, rs.getInt("COL1"));
+            assertEquals(13, rs.getInt("COL2"));
+            assertEquals("view5", rs.getString("VIEW_COL2"));
+            assertEquals(17, rs.getInt("VIEW_COL4"));
+            assertFalse(rs.next());
+
+            // query view
+            rs = stmt.executeQuery("SELECT * FROM VIEWOFTABLE");
+            assertTrue(rs.next());
+            assertEquals("view1", rs.getString("ID"));
+            assertEquals(12, rs.getInt("COL1"));
+            assertEquals(13, rs.getInt("COL2"));
+            assertEquals(14, rs.getInt("VIEW_COL1"));
+            assertEquals("view5", rs.getString("VIEW_COL2"));
+            assertEquals("view6", rs.getString("VIEW_COL3"));
+            assertEquals(17, rs.getInt("VIEW_COL4"));
+            assertEquals(18, rs.getInt("VIEW_COL5"));
+            assertEquals("view9", rs.getString("VIEW_COL6"));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+    
+    @Test
+    public void testAddExistingViewPkColumnToBaseTableWithViews() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        try {       
+            conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
+                    + " ID char(10) NOT NULL,"
+                    + " COL1 integer NOT NULL,"
+                    + " COL2 integer NOT NULL,"
+                    + " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
+                    + " )");
+            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
+            
+            conn.createStatement().execute("CREATE VIEW VIEWOFTABLE ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) CONSTRAINT pk PRIMARY KEY (VIEW_COL1, VIEW_COL2)) AS SELECT * FROM TABLEWITHVIEW");
+            assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+            
+            // upsert single row into view
+            String dml = "UPSERT INTO VIEWOFTABLE VALUES(?,?,?,?,?)";
+            PreparedStatement stmt = conn.prepareStatement(dml);
+            stmt.setString(1, "view1");
+            stmt.setInt(2, 12);
+            stmt.setInt(3, 13);
+            stmt.setInt(4, 14);
+            stmt.setString(5, "view5");
+            stmt.execute();
+            conn.commit();
+            
+            try {
+                // should fail because there we have to add both VIEW_COL1 and VIEW_COL2 to the pk
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR(256) PRIMARY KEY");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+            
+            try {
+                // should fail because there we have to add both VIEW_COL1 and VIEW_COL2  to the pk 
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+            
+            try {
+                // should fail because there we have to add both VIEW_COL1 and VIEW_COL2 to the pk
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) PRIMARY KEY");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+            
+            try {
+                // should fail because there we have to add both VIEW_COL1 and VIEW_COL2  to the pk 
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY, VIEW_COL2 VARCHAR(256)");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+            
+            try {
+                // should fail because there we have to add both VIEW_COL1 and VIEW_COL2 to the pk in the right order
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR(256) PRIMARY KEY, VIEW_COL1 DECIMAL(10,2) PRIMARY KEY");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+            
+            try {
+                // should fail because there we have to add both VIEW_COL1 and VIEW_COL2 with the right sort order
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY DESC, VIEW_COL2 VARCHAR(256) PRIMARY KEY");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+            
+            // add the pk column of the view to the base table
+            conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY, VIEW_COL2 VARCHAR(256) PRIMARY KEY");
+            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 5, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+            assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 5, 5, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+            
+            // query table
+            ResultSet rs = stmt.executeQuery("SELECT * FROM TABLEWITHVIEW");
+            assertTrue(rs.next());
+            assertEquals("view1", rs.getString("ID"));
+            assertEquals(12, rs.getInt("COL1"));
+            assertEquals(13, rs.getInt("COL2"));
+            assertEquals(14, rs.getInt("VIEW_COL1"));
+            assertEquals("view5", rs.getString("VIEW_COL2"));
+            assertFalse(rs.next());
+
+            // query view
+            rs = stmt.executeQuery("SELECT * FROM VIEWOFTABLE");
+            assertTrue(rs.next());
+            assertEquals("view1", rs.getString("ID"));
+            assertEquals(12, rs.getInt("COL1"));
+            assertEquals(13, rs.getInt("COL2"));
+            assertEquals(14, rs.getInt("VIEW_COL1"));
+            assertEquals("view5", rs.getString("VIEW_COL2"));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+    
+    @Test
+    public void testAddExistingViewPkColumnToBaseTableWithMultipleViews() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        try {       
+            conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
+                    + " ID char(10) NOT NULL,"
+                    + " COL1 integer NOT NULL,"
+                    + " COL2 integer NOT NULL,"
+                    + " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
+                    + " )");
+            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
+            
+            conn.createStatement().execute("CREATE VIEW VIEWOFTABLE1 ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) CONSTRAINT pk PRIMARY KEY (VIEW_COL1, VIEW_COL2)) AS SELECT * FROM TABLEWITHVIEW");
+            assertTableDefinition(conn, "VIEWOFTABLE1", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+            
+            conn.createStatement().execute("CREATE VIEW VIEWOFTABLE2 ( VIEW_COL3 VARCHAR(256), VIEW_COL4 DECIMAL(10,2) CONSTRAINT pk PRIMARY KEY (VIEW_COL3, VIEW_COL4)) AS SELECT * FROM TABLEWITHVIEW");
+            assertTableDefinition(conn, "VIEWOFTABLE2", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL3", "VIEW_COL4");
+            
+            try {
+                // should fail because there are two view with different pk columns
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL PRIMARY KEY, VIEW_COL2 VARCHAR PRIMARY KEY");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+            
+            try {
+                // should fail because there are two view with different pk columns
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL3 VARCHAR PRIMARY KEY, VIEW_COL4 DECIMAL PRIMARY KEY");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+            
+            try {
+                // should fail because slot positions of pks are different
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL PRIMARY KEY, VIEW_COL2 VARCHAR PRIMARY KEY, VIEW_COL3 VARCHAR PRIMARY KEY, VIEW_COL4 DECIMAL PRIMARY KEY");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+            
+            try {
+                // should fail because slot positions of pks are different
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL3 VARCHAR PRIMARY KEY, VIEW_COL4 DECIMAL PRIMARY KEY, VIEW_COL1 DECIMAL PRIMARY KEY, VIEW_COL2 VARCHAR PRIMARY KEY");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+        } finally {
+            conn.close();
+        }
+    }
+    
+    @Test
+    public void testAddExistingViewPkColumnToBaseTableWithMultipleViewsHavingSamePks() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        try {       
+            conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
+                    + " ID char(10) NOT NULL,"
+                    + " COL1 integer NOT NULL,"
+                    + " COL2 integer NOT NULL,"
+                    + " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
+                    + " )");
+            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
+            
+            conn.createStatement().execute("CREATE VIEW VIEWOFTABLE1 ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) CONSTRAINT pk PRIMARY KEY (VIEW_COL1, VIEW_COL2)) AS SELECT * FROM TABLEWITHVIEW");
+            assertTableDefinition(conn, "VIEWOFTABLE1", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+            
+            conn.createStatement().execute("CREATE VIEW VIEWOFTABLE2 ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) CONSTRAINT pk PRIMARY KEY (VIEW_COL1, VIEW_COL2)) AS SELECT * FROM TABLEWITHVIEW");
+            assertTableDefinition(conn, "VIEWOFTABLE2", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+            
+            // upsert single row into both view
+            String dml = "UPSERT INTO VIEWOFTABLE1 VALUES(?,?,?,?,?)";
+            PreparedStatement stmt = conn.prepareStatement(dml);
+            stmt.setString(1, "view1");
+            stmt.setInt(2, 12);
+            stmt.setInt(3, 13);
+            stmt.setInt(4, 14);
+            stmt.setString(5, "view5");
+            stmt.execute();
+            conn.commit();
+            dml = "UPSERT INTO VIEWOFTABLE2 VALUES(?,?,?,?,?)";
+            stmt = conn.prepareStatement(dml);
+            stmt.setString(1, "view1");
+            stmt.setInt(2, 12);
+            stmt.setInt(3, 13);
+            stmt.setInt(4, 14);
+            stmt.setString(5, "view5");
+            stmt.execute();
+            conn.commit();
+            
+            try {
+                // should fail because the view have two extra columns in their pk
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+            
+            try {
+                // should fail because the view have two extra columns in their pk
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR(256) PRIMARY KEY");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+            
+            try {
+                // should fail because slot positions of pks are different
+                conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 DECIMAL(10,2) PRIMARY KEY, VIEW_COL1 VARCHAR(256) PRIMARY KEY");
+                fail();
+            }
+            catch (SQLException e) {
+                assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+            
+            conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY, VIEW_COL2 VARCHAR(256) PRIMARY KEY");
+            assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 5, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+            assertTableDefinition(conn, "VIEWOFTABLE1", PTableType.VIEW, "TABLEWITHVIEW", 1, 5, 5, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+            assertTableDefinition(conn, "VIEWOFTABLE2", PTableType.VIEW, "TABLEWITHVIEW", 1, 5, 5, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+            
+            // query table
+            ResultSet rs = stmt.executeQuery("SELECT * FROM TABLEWITHVIEW");
+            assertTrue(rs.next());
+            assertEquals("view1", rs.getString("ID"));
+            assertEquals(12, rs.getInt("COL1"));
+            assertEquals(13, rs.getInt("COL2"));
+            assertEquals(14, rs.getInt("VIEW_COL1"));
+            assertEquals("view5", rs.getString("VIEW_COL2"));
+            assertFalse(rs.next());
+
+            // query both views
+            rs = stmt.executeQuery("SELECT * FROM VIEWOFTABLE1");
+            assertTrue(rs.next());
+            assertEquals("view1", rs.getString("ID"));
+            assertEquals(12, rs.getInt("COL1"));
+            assertEquals(13, rs.getInt("COL2"));
+            assertEquals(14, rs.getInt("VIEW_COL1"));
+            assertEquals("view5", rs.getString("VIEW_COL2"));
+            assertFalse(rs.next());
+            rs = stmt.executeQuery("SELECT * FROM VIEWOFTABLE2");
+            assertTrue(rs.next());
+            assertEquals("view1", rs.getString("ID"));
+            assertEquals(12, rs.getInt("COL1"));
+            assertEquals(13, rs.getInt("COL2"));
+            assertEquals(14, rs.getInt("VIEW_COL1"));
+            assertEquals("view5", rs.getString("VIEW_COL2"));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+    
+    private void assertTableDefinition(Connection conn, String tableName, PTableType tableType, String parentTableName, int sequenceNumber, int columnCount, int baseColumnCount, String... columnName) throws Exception {
+        PreparedStatement p = conn.prepareStatement("SELECT * FROM SYSTEM.CATALOG WHERE TABLE_NAME=? AND TABLE_TYPE=?");
+        p.setString(1, tableName);
+        p.setString(2, tableType.getSerializedValue());
+        ResultSet rs = p.executeQuery();
+        assertTrue(rs.next());
+        assertEquals(getSystemCatalogEntriesForTable(conn, tableName, "Mismatch in BaseColumnCount"), baseColumnCount, rs.getInt("BASE_COLUMN_COUNT"));
+        assertEquals(getSystemCatalogEntriesForTable(conn, tableName, "Mismatch in columnCount"), columnCount, rs.getInt("COLUMN_COUNT"));
+        assertEquals(getSystemCatalogEntriesForTable(conn, tableName, "Mismatch in sequenceNumber"), sequenceNumber, rs.getInt("TABLE_SEQ_NUM"));
+        rs.close();
+
+        ResultSet parentTableColumnsRs = null; 
+        if (parentTableName != null) {
+            parentTableColumnsRs = conn.getMetaData().getColumns(null, null, parentTableName, null);
+            parentTableColumnsRs.next();
+        }
+        
+        ResultSet viewColumnsRs = conn.getMetaData().getColumns(null, null, tableName, null);
+        for (int i = 0; i < columnName.length; i++) {
+            if (columnName[i] != null) {
+                assertTrue(viewColumnsRs.next());
+                assertEquals(getSystemCatalogEntriesForTable(conn, tableName, "Mismatch in columnName: i=" + i), columnName[i], viewColumnsRs.getString(PhoenixDatabaseMetaData.COLUMN_NAME));
+                int viewColOrdinalPos = viewColumnsRs.getInt(PhoenixDatabaseMetaData.ORDINAL_POSITION);
+                assertEquals(getSystemCatalogEntriesForTable(conn, tableName, "Mismatch in ordinalPosition: i=" + i), i+1, viewColOrdinalPos);
+                // validate that all the columns in the base table are present in the view   
+                if (parentTableColumnsRs != null && !parentTableColumnsRs.isAfterLast()) {
+                    ResultSetMetaData parentTableColumnsMetadata = parentTableColumnsRs.getMetaData();
+                    assertEquals(parentTableColumnsMetadata.getColumnCount(), viewColumnsRs.getMetaData().getColumnCount());
+                    int parentTableColOrdinalRs = parentTableColumnsRs.getInt(PhoenixDatabaseMetaData.ORDINAL_POSITION);
+                    assertEquals(getSystemCatalogEntriesForTable(conn, tableName, "Mismatch in ordinalPosition of view and base table for i=" + i), parentTableColOrdinalRs, viewColOrdinalPos);
+                    for (int columnIndex = 1; columnIndex < parentTableColumnsMetadata.getColumnCount(); columnIndex++) {
+                        String viewColumnValue = viewColumnsRs.getString(columnIndex);
+                        String parentTableColumnValue = parentTableColumnsRs.getString(columnIndex);
+                        if (!Objects.equal(viewColumnValue, parentTableColumnValue)) {
+                            if (parentTableColumnsMetadata.getColumnName(columnIndex).equals(PhoenixDatabaseMetaData.TABLE_NAME)) {
+                                assertEquals(parentTableName, parentTableColumnValue);
+                                assertEquals(tableName, viewColumnValue);
+                            } 
+                        }
+                    }
+                    parentTableColumnsRs.next();
+                }
+            }
+        }
+        assertFalse(getSystemCatalogEntriesForTable(conn, tableName, ""), viewColumnsRs.next());
+    }
+    
+    private String getSystemCatalogEntriesForTable(Connection conn, String tableName, String message) throws Exception {
+        StringBuilder sb = new StringBuilder(message);
+        sb.append("\n\n\n");
+        ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM SYSTEM.CATALOG WHERE TABLE_NAME='"+ tableName +"'");
+        ResultSetMetaData metaData = rs.getMetaData();
+        int rowNum = 0;
+        while (rs.next()) {
+            sb.append(rowNum++).append("------\n");
+            for (int i = 1; i <= metaData.getColumnCount(); i++) {
+                sb.append("\t").append(metaData.getColumnLabel(i)).append("=").append(rs.getString(i)).append("\n");
+            }
+            sb.append("\n");
+        }
+        rs.close();
+        return sb.toString();
+    }
+    
+    @Test
+    public void testCacheInvalidatedAfterAddingColumnToBaseTableWithViews() throws Exception {
+        String baseTable = "testCacheInvalidatedAfterAddingColumnToBaseTableWithViews";
+        String viewName = baseTable + "_view";
+        String tenantId = "tenantId";
+        try (Connection globalConn = DriverManager.getConnection(getUrl())) {
+            String tableDDL = "CREATE TABLE " + baseTable + " (TENANT_ID VARCHAR NOT NULL, PK1 VARCHAR NOT NULL, V1 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, PK1)) MULTI_TENANT = true " ;
+            globalConn.createStatement().execute(tableDDL);
+            Properties tenantProps = new Properties();
+            tenantProps.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, tenantId);
+            // create a tenant specific view
+            try (Connection tenantConn =  DriverManager.getConnection(getUrl(), tenantProps)) {
+                String viewDDL = "CREATE VIEW " + viewName + " AS SELECT * FROM " + baseTable;
+                tenantConn.createStatement().execute(viewDDL);
+                
+                // Add a column to the base table using global connection
+                globalConn.createStatement().execute("ALTER TABLE " + baseTable + " ADD NEW_COL VARCHAR");
+
+                // Check now whether the tenant connection can see the column that was added
+                tenantConn.createStatement().execute("SELECT NEW_COL FROM " + viewName);
+                tenantConn.createStatement().execute("SELECT NEW_COL FROM " + baseTable);
+            }
+        }
+    }
+    
+    @Test
+    public void testDropColumnOnTableWithViewsNotAllowed() throws Exception {
+        String baseTable = "testDropColumnOnTableWithViewsNotAllowed";
+        String viewName = baseTable + "_view";
+        try (Connection conn = DriverManager.getConnection(getUrl())) {
+            String tableDDL = "CREATE TABLE " + baseTable + " (PK1 VARCHAR NOT NULL PRIMARY KEY, V1 VARCHAR, V2 VARCHAR)";
+            conn.createStatement().execute(tableDDL);
+            
+            String viewDDL = "CREATE VIEW " + viewName + " AS SELECT * FROM " + baseTable;
+            conn.createStatement().execute(viewDDL);
+            
+            String dropColumn = "ALTER TABLE " + baseTable + " DROP COLUMN V2";
+            try {
+                conn.createStatement().execute(dropColumn);
+                fail("Dropping column on a base table that has views is not allowed");
+            } catch (SQLException e) {  
+                assertEquals(CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+            }
+        }
+    }
+    
+    @Test
+    public void testAlteringViewThatHasChildViews() throws Exception {
+        String baseTable = "testAlteringViewThatHasChildViews";
+        String childView = "childView";
+        String grandChildView = "grandChildView";
+        try (Connection conn = DriverManager.getConnection(getUrl())) {
+            String baseTableDDL =
+                    "CREATE TABLE " +  baseTable + " (TENANT_ID VARCHAR NOT NULL, PK2 VARCHAR NOT NULL, V1 VARCHAR, V2 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, PK2))";
+            conn.createStatement().execute(baseTableDDL);
+
+            String childViewDDL = "CREATE VIEW " + childView + " AS SELECT * FROM " + baseTable;
+            conn.createStatement().execute(childViewDDL);
+
+            String addColumnToChildViewDDL =
+                    "ALTER VIEW " + childView + " ADD CHILD_VIEW_COL VARCHAR";
+            conn.createStatement().execute(addColumnToChildViewDDL);
+
+            String grandChildViewDDL =
+                    "CREATE VIEW " + grandChildView + " AS SELECT * FROM " + childView;
+            conn.createStatement().execute(grandChildViewDDL);
+
+            // dropping base table column from child view should succeed
+            String dropColumnFromChildView = "ALTER VIEW " + childView + " DROP COLUMN V2";
+            conn.createStatement().execute(dropColumnFromChildView);
+
+            // dropping view specific column from child view should succeed
+            dropColumnFromChildView = "ALTER VIEW " + childView + " DROP COLUMN CHILD_VIEW_COL";
+            conn.createStatement().execute(dropColumnFromChildView);
+            
+            // Adding column to view that has child views is allowed
+            String addColumnToChildView = "ALTER VIEW " + childView + " ADD V5 VARCHAR";
+            conn.createStatement().execute(addColumnToChildView);
+            // V5 column should be visible now for childView
+            conn.createStatement().execute("SELECT V5 FROM " + childView);    
+            
+            // However, column V5 shouldn't have propagated to grandChildView. Not till PHOENIX-2054 is fixed.
+            try {
+                conn.createStatement().execute("SELECT V5 FROM " + grandChildView);
+            } catch (SQLException e) {
+                assertEquals(SQLExceptionCode.COLUMN_NOT_FOUND.getErrorCode(), e.getErrorCode());
+            }
+
+            // dropping column from the grand child view, however, should work.
+            String dropColumnFromGrandChildView =
+                    "ALTER VIEW " + grandChildView + " DROP COLUMN CHILD_VIEW_COL";
+            conn.createStatement().execute(dropColumnFromGrandChildView);
+
+            // similarly, dropping column inherited from the base table should work.
+            dropColumnFromGrandChildView = "ALTER VIEW " + grandChildView + " DROP COLUMN V2";
+            conn.createStatement().execute(dropColumnFromGrandChildView);
+        }
+    }
+    
+    @Test
+    public void testDivergedViewsStayDiverged() throws Exception {
+        String baseTable = "testDivergedViewsStayDiverged";
+        String view1 = baseTable + "_view1";
+        String view2 = baseTable + "_view2";
+        try (Connection conn = DriverManager.getConnection(getUrl())) {
+            String tableDDL = "CREATE TABLE " + baseTable + " (PK1 VARCHAR NOT NULL PRIMARY KEY, V1 VARCHAR, V2 VARCHAR)";
+            conn.createStatement().execute(tableDDL);
+            
+            String viewDDL = "CREATE VIEW " + view1 + " AS SELECT * FROM " + baseTable;
+            conn.createStatement().execute(viewDDL);
+            
+            viewDDL = "CREATE VIEW " + view2 + " AS SELECT * FROM " + baseTable;
+            conn.createStatement().execute(viewDDL);
+            
+            // Drop the column inherited from base table to make it diverged
+            String dropColumn = "ALTER VIEW " + view1 + " DROP COLUMN V2";
+            conn.createStatement().execute(dropColumn);
+            
+            String alterBaseTable = "ALTER TABLE " + baseTable + " ADD V3 VARCHAR";
+            conn.createStatement().execute(alterBaseTable);
+            
+            // Column V3 shouldn't have propagated to the diverged view.
+            String sql = "SELECT V3 FROM " + view1;
+            try {
+                conn.createStatement().execute(sql);
+            } catch (SQLException e) {
+                assertEquals(SQLExceptionCode.COLUMN_NOT_FOUND.getErrorCode(), e.getErrorCode());
+            }
+            
+            // However, column V3 should have propagated to the non-diverged view.
+            sql = "SELECT V3 FROM " + view2;
+            conn.createStatement().execute(sql);
+        } 
+    }
+    
+    @Test
+    public void testAddingColumnToBaseTablePropagatesToEntireViewHierarchy() throws Exception {
+        String baseTable = "testViewHierarchy";
+        String view1 = "view1";
+        String view2 = "view2";
+        String view3 = "view3";
+        String view4 = "view4";
+        /*                                     baseTable
+                                 /                  |               \ 
+                         view1(tenant1)    view3(tenant2)          view4(global)
+                          /
+                        view2(tenant1)  
+        */
+        try (Connection conn = DriverManager.getConnection(getUrl())) {
+            String baseTableDDL = "CREATE TABLE " + baseTable + " (TENANT_ID VARCHAR NOT NULL, PK1 VARCHAR NOT NULL, V1 VARCHAR, V2 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, PK1)) MULTI_TENANT = true ";
+            conn.createStatement().execute(baseTableDDL);
+            
+            try (Connection tenant1Conn = getTenantConnection("tenant1")) {
+                String view1DDL = "CREATE VIEW " + view1 + " AS SELECT * FROM " + baseTable;
+                tenant1Conn.createStatement().execute(view1DDL);
+                
+                String view2DDL = "CREATE VIEW " + view2 + " AS SELECT * FROM " + view1;
+                tenant1Conn.createStatement().execute(view2DDL);
+            }
+            
+            try (Connection tenant2Conn = getTenantConnection("tenant2")) {
+                String view3DDL = "CREATE VIEW " + view3 + " AS SELECT * FROM " + baseTable;
+                tenant2Conn.createStatement().execute(view3DDL);
+            }
+            
+            String view4DDL = "CREATE VIEW " + view4 + " AS SELECT * FROM " + baseTable;
+            conn.createStatement().execute(view4DDL);
+            
+            String alterBaseTable = "ALTER TABLE " + baseTable + " ADD V3 VARCHAR";
+            conn.createStatement().execute(alterBaseTable);
+            
+            // verify that the column is visible to view4
+            conn.createStatement().execute("SELECT V3 FROM " + view4);
+            
+            // verify that the column is visible to view1 and view2
+            try (Connection tenant1Conn = getTenantConnection("tenant1")) {
+                tenant1Conn.createStatement().execute("SELECT V3 from " + view1);
+                tenant1Conn.createStatement().execute("SELECT V3 from " + view2);
+            }
+            
+            // verify that the column is visible to view3
+            try (Connection tenant2Conn = getTenantConnection("tenant2")) {
+                tenant2Conn.createStatement().execute("SELECT V3 from " + view3);
+            }
+            
+        }
+           
+    }
+    
+    @Test
+    public void testChangingPKOfBaseTableChangesPKForAllViews() throws Exception {
+        String baseTable = "testChangePKOfBaseTable";
+        String view1 = "view1";
+        String view2 = "view2";
+        String view3 = "view3";
+        String view4 = "view4";
+        /*                                     baseTable
+                                 /                  |               \ 
+                         view1(tenant1)    view3(tenant2)          view4(global)
+                          /
+                        view2(tenant1)  
+         */
+        Connection tenant1Conn = null, tenant2Conn = null;
+        try (Connection globalConn = DriverManager.getConnection(getUrl())) {
+            String baseTableDDL = "CREATE TABLE "
+                    + baseTable
+                    + " (TENANT_ID VARCHAR NOT NULL, PK1 VARCHAR NOT NULL, V1 VARCHAR, V2 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, PK1)) MULTI_TENANT = true ";
+            globalConn.createStatement().execute(baseTableDDL);
+
+            tenant1Conn = getTenantConnection("tenant1");
+            String view1DDL = "CREATE VIEW " + view1 + " AS SELECT * FROM " + baseTable;
+            tenant1Conn.createStatement().execute(view1DDL);
+
+            String view2DDL = "CREATE VIEW " + view2 + " AS SELECT * FROM " + view1;
+            tenant1Conn.createStatement().execute(view2DDL);
+
+            tenant2Conn = getTenantConnection("tenant2");
+            String view3DDL = "CREATE VIEW " + view3 + " AS SELECT * FROM " + baseTable;
+            tenant2Conn.createStatement().execute(view3DDL);
+
+            String view4DDL = "CREATE VIEW " + view4 + " AS SELECT * FROM " + baseTable;
+            globalConn.createStatement().execute(view4DDL);
+
+            String alterBaseTable = "ALTER TABLE " + baseTable + " ADD NEW_PK varchar primary key ";
+            globalConn.createStatement().execute(alterBaseTable);
+            
+            // verify that the new column new_pk is now part of the primary key for the entire hierarchy
+            
+            globalConn.createStatement().execute("SELECT * FROM " + baseTable);
+            assertTrue(checkColumnPartOfPk(globalConn.unwrap(PhoenixConnection.class), "NEW_PK", baseTable));
+            
+            tenant1Conn.createStatement().execute("SELECT * FROM " + view1);
+            assertTrue(checkColumnPartOfPk(tenant1Conn.unwrap(PhoenixConnection.class), "NEW_PK", view1));
+            
+            tenant1Conn.createStatement().execute("SELECT * FROM " + view2);
+            assertTrue(checkColumnPartOfPk(tenant1Conn.unwrap(PhoenixConnection.class), "NEW_PK", view2));
+            
+            tenant2Conn.createStatement().execute("SELECT * FROM " + view3);
+            assertTrue(checkColumnPartOfPk(tenant2Conn.unwrap(PhoenixConnection.class), "NEW_PK", view3));
+            
+            globalConn.createStatement().execute("SELECT * FROM " + view4);
+            assertTrue(checkColumnPartOfPk(globalConn.unwrap(PhoenixConnection.class), "NEW_PK", view4));
+
+        } finally {
+            if (tenant1Conn != null) {
+                try {
+                    tenant1Conn.close();
+                } catch (Throwable ignore) {}
+            }
+            if (tenant2Conn != null) {
+                try {
+                    tenant2Conn.close();
+                } catch (Throwable ignore) {}
+            }
+        }
+
+    }
+    
+    private boolean checkColumnPartOfPk(PhoenixConnection conn, String columnName, String tableName) throws SQLException {
+        String normalizedTableName = SchemaUtil.normalizeIdentifier(tableName);
+        PTable table = conn.getMetaDataCache().getTable(new PTableKey(conn.getTenantId(), normalizedTableName));
+        List<PColumn> pkCols = table.getPKColumns();
+        String normalizedColumnName = SchemaUtil.normalizeIdentifier(columnName);
+        for (PColumn pkCol : pkCols) {
+            if (pkCol.getName().getString().equals(normalizedColumnName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    private int getIndexOfPkColumn(PhoenixConnection conn, String columnName, String tableName) throws SQLException {
+        String normalizedTableName = SchemaUtil.normalizeIdentifier(tableName);
+        PTable table = conn.getMetaDataCache().getTable(new PTableKey(conn.getTenantId(), normalizedTableName));
+        List<PColumn> pkCols = table.getPKColumns();
+        String normalizedColumnName = SchemaUtil.normalizeIdentifier(columnName);
+        int i = 0;
+        for (PColumn pkCol : pkCols) {
+            if (pkCol.getName().getString().equals(normalizedColumnName)) {
+                return i;
+            }
+            i++;
+        }
+        return -1;
+    }
+    
+    private Connection getTenantConnection(String tenantId) throws Exception {
+        Properties tenantProps = new Properties();
+        tenantProps.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, tenantId);
+        return DriverManager.getConnection(getUrl(), tenantProps);
+    }
+    
+    @Test
+    public void testAddPKColumnToBaseTableWhoseViewsHaveIndices() throws Exception {
+        String baseTable = "testAddPKColumnToBaseTableWhoseViewsHaveIndices";
+        String view1 = "view1";
+        String view2 = "view2";
+        String view3 = "view3";
+        String tenant1 = "tenant1";
+        String tenant2 = "tenant2";
+        String view2Index = view2 + "_idx";
+        String view3Index = view3 + "_idx";
+        /*                          baseTable(mutli-tenant)
+                                 /                           \                
+                         view1(tenant1)                  view3(tenant2, index) 
+                          /
+                        view2(tenant1, index)  
+         */
+        try (Connection globalConn = DriverManager.getConnection(getUrl())) {
+            // make sure that the tables are empty, but reachable
+            globalConn
+            .createStatement()
+            .execute(
+                    "CREATE TABLE "
+                            + baseTable
+                            + " (TENANT_ID VARCHAR NOT NULL, K1 varchar not null, V1 VARCHAR, V2 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, K1)) MULTI_TENANT = true ");
+
+        }
+        try (Connection tenantConn = getTenantConnection(tenant1)) {
+            // create tenant specific view for tenant1 - view1
+            tenantConn.createStatement().execute("CREATE VIEW " + view1 + " AS SELECT * FROM " + baseTable);
+            PhoenixConnection phxConn = tenantConn.unwrap(PhoenixConnection.class);
+            assertEquals(0, getTableSequenceNumber(phxConn, view1));
+            assertEquals(2, getMaxKeySequenceNumber(phxConn, view1));
+
+            // create a view - view2 on view - view1
+            tenantConn.createStatement().execute("CREATE VIEW " + view2 + " AS SELECT * FROM " + view1);
+            assertEquals(0, getTableSequenceNumber(phxConn, view2));
+            assertEquals(2, getMaxKeySequenceNumber(phxConn, view2));
+
+
+            // create an index on view2
+            tenantConn.createStatement().execute("CREATE INDEX " + view2Index + " ON " + view2 + " (v1) include (v2)");
+            assertEquals(0, getTableSequenceNumber(phxConn, view2Index));
+            assertEquals(4, getMaxKeySequenceNumber(phxConn, view2Index));
+        }
+        try (Connection tenantConn = getTenantConnection(tenant2)) {
+            // create tenant specific view for tenant2 - view3
+            tenantConn.createStatement().execute("CREATE VIEW " + view3 + " AS SELECT * FROM " + baseTable);
+            PhoenixConnection phxConn = tenantConn.unwrap(PhoenixConnection.class);
+            assertEquals(0, getTableSequenceNumber(phxConn, view3));
+            assertEquals(2, getMaxKeySequenceNumber(phxConn, view3));
+
+
+            // create an index on view3
+            tenantConn.createStatement().execute("CREATE INDEX " + view3Index + " ON " + view3 + " (v1) include (v2)");
+            assertEquals(0, getTableSequenceNumber(phxConn, view3Index));
+            assertEquals(4, getMaxKeySequenceNumber(phxConn, view3Index));
+
+
+        }
+
+        // alter the base table by adding 1 non-pk and 2 pk columns
+        try (Connection globalConn = DriverManager.getConnection(getUrl())) {
+            globalConn.createStatement().execute("ALTER TABLE " + baseTable + " ADD v3 VARCHAR, k2 VARCHAR PRIMARY KEY, k3 VARCHAR PRIMARY KEY");
+            assertEquals(4, getMaxKeySequenceNumber(globalConn.unwrap(PhoenixConnection.class), baseTable));
+
+            // Upsert records in the base table
+            String upsert = "UPSERT INTO " + baseTable + " (TENANT_ID, K1, K2, K3, V1, V2, V3) VALUES (?, ?, ?, ?, ?, ?, ?)";
+            PreparedStatement stmt = globalConn.prepareStatement(upsert);
+            stmt.setString(1, tenant1);
+            stmt.setString(2, "K1");
+            stmt.setString(3, "K2");
+            stmt.setString(4, "K3");
+            stmt.setString(5, "V1");
+            stmt.setString(6, "V2");
+            stmt.setString(7, "V3");
+            stmt.executeUpdate();
+            stmt.setString(1, tenant2);
+            stmt.setString(2, "K11");
+            stmt.setString(3, "K22");
+            stmt.setString(4, "K33");
+            stmt.setString(5, "V11");
+            stmt.setString(6, "V22");
+            stmt.setString(7, "V33");
+            stmt.executeUpdate();
+            globalConn.commit();
+        }
+
+        // Verify now that the sequence number of data table, indexes and views have changed.
+        // Also verify that the newly added pk columns show up as pk columns of data table, indexes and views.
+        try (Connection tenantConn = getTenantConnection(tenant1)) {
+
+            ResultSet rs = tenantConn.createStatement().executeQuery("SELECT K2, K3, V3 FROM " + view1);
+            PhoenixConnection phxConn = tenantConn.unwrap(PhoenixConnection.class);
+            assertEquals(2, getIndexOfPkColumn(phxConn, "k2", view1));
+            assertEquals(3, getIndexOfPkColumn(phxConn, "k3", view1));
+            assertEquals(1, getTableSequenceNumber(phxConn, view1));
+            assertEquals(4, getMaxKeySequenceNumber(phxConn, view1));
+            verifyNewColumns(rs, "K2", "K3", "V3");
+
+
+            rs = tenantConn.createStatement().executeQuery("SELECT K2, K3, V3 FROM " + view2);
+            assertEquals(2, getIndexOfPkColumn(phxConn, "k2", view2));
+            assertEquals(3, getIndexOfPkColumn(phxConn, "k3", view2));
+            assertEquals(1, getTableSequenceNumber(phxConn, view2));
+            assertEquals(4, getMaxKeySequenceNumber(phxConn, view2));
+            verifyNewColumns(rs, "K2", "K3", "V3");
+
+            assertEquals(4, getIndexOfPkColumn(phxConn, IndexUtil.getIndexColumnName(null, "k2"), view2Index));
+            assertEquals(5, getIndexOfPkColumn(phxConn, IndexUtil.getIndexColumnName(null, "k3"), view2Index));
+            assertEquals(1, getTableSequenceNumber(phxConn, view2Index));
+            assertEquals(6, getMaxKeySequenceNumber(phxConn, view2Index));
+        }
+        try (Connection tenantConn = getTenantConnection(tenant2)) {
+            ResultSet rs = tenantConn.createStatement().executeQuery("SELECT K2, K3, V3 FROM " + view3);
+            PhoenixConnection phxConn = tenantConn.unwrap(PhoenixConnection.class);
+            assertEquals(2, getIndexOfPkColumn(phxConn, "k2", view3));
+            assertEquals(3, getIndexOfPkColumn(phxConn, "k3", view3));
+            assertEquals(1, getTableSequenceNumber(phxConn, view3));
+            verifyNewColumns(rs, "K22", "K33", "V33");
+
+            assertEquals(4, getIndexOfPkColumn(phxConn, IndexUtil.getIndexColumnName(null, "k2"), view3Index));
+            assertEquals(5, getIndexOfPkColumn(phxConn, IndexUtil.getIndexColumnName(null, "k3"), view3Index));
+            assertEquals(1, getTableSequenceNumber(phxConn, view3Index));
+            assertEquals(6, getMaxKeySequenceNumber(phxConn, view3Index));
+        }
+        // Verify that the index is actually being used when using newly added pk col
+        try (Connection tenantConn = getTenantConnection(tenant1)) {
+            String upsert = "UPSERT INTO " + view2 + " (K1, K2, K3, V1, V2, V3) VALUES ('key1', 'key2', 'key3', 'value1', 'value2', 'value3')";
+            tenantConn.createStatement().executeUpdate(upsert);
+            tenantConn.commit();
+            Statement stmt = tenantConn.createStatement();
+            String sql = "SELECT V2 FROM " + view2 + " WHERE V1 = 'value1' AND K3 = 'key3'";
+            QueryPlan plan = stmt.unwrap(PhoenixStatement.class).optimizeQuery(sql);
+            assertTrue(plan.getTableRef().getTable().getName().getString().equals(SchemaUtil.normalizeIdentifier(view2Index)));
+            ResultSet rs = tenantConn.createStatement().executeQuery(sql);
+            verifyNewColumns(rs, "value2");
+        }
+
+    }
+    
+    @Test
+    public void testAddingPkAndKeyValueColumnsToBaseTableWithDivergedView() throws Exception {
+        String baseTable = "testAlteringPkOfBaseTableWithDivergedView".toUpperCase();
+        String view1 = "view1".toUpperCase();
+        String divergedView = "divergedView".toUpperCase();
+        String divergedViewIndex = divergedView + "_IDX";
+        /*                                     baseTable
+                                 /                  |                
+                         view1(tenant1)         divergedView(tenant2)    
+                            
+        */
+        try (Connection conn = DriverManager.getConnection(getUrl())) {
+            String baseTableDDL = "CREATE TABLE " + baseTable + " (TENANT_ID VARCHAR NOT NULL, PK1 VARCHAR NOT NULL, V1 VARCHAR, V2 VARCHAR, V3 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, PK1)) MULTI_TENANT = true ";
+            conn.createStatement().execute(baseTableDDL);
+            
+            try (Connection tenant1Conn = getTenantConnection("tenant1")) {
+                String view1DDL = "CREATE VIEW " + view1 + " ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 CHAR(256)) AS SELECT * FROM " + baseTable;
+                tenant1Conn.createStatement().execute(view1DDL);
+            }
+            
+            try (Connection tenant2Conn = getTenantConnection("tenant2")) {
+                String divergedViewDDL = "CREATE VIEW " + divergedView + " ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 CHAR(256)) AS SELECT * FROM " + baseTable;
+                tenant2Conn.createStatement().execute(divergedViewDDL);
+                // Drop column V2 from the view to have it diverge from the base table
+                tenant2Conn.createStatement().execute("ALTER VIEW " + divergedView + " DROP COLUMN V2");
+                
+                // create an index on the diverged view
+                String indexDDL = "CREATE INDEX " + divergedViewIndex + " ON " + divergedView + " (V1) include (V3)";
+                tenant2Conn.createStatement().execute(indexDDL);
+            }
+            
+            String alterBaseTable = "ALTER TABLE " + baseTable + " ADD KV VARCHAR, PK2 VARCHAR PRIMARY KEY";
+            conn.createStatement().execute(alterBaseTable);
+            
+            
+            // verify that the both columns were added to view1
+            try (Connection tenant1Conn = getTenantConnection("tenant1")) {
+                tenant1Conn.createStatement().execute("SELECT KV from " + view1);
+                tenant1Conn.createStatement().execute("SELECT PK2 from " + view1);
+            }
+            
+            // verify that only the primary key column PK2 was added to diverged view
+            try (Connection tenant2Conn = getTenantConnection("tenant2")) {
+                tenant2Conn.createStatement().execute("SELECT PK2 from " + divergedView);
+                try {
+                    tenant2Conn.createStatement().execute("SELECT KV FROM " + divergedView);
+                } catch (SQLException e) {
+                    assertEquals(SQLExceptionCode.COLUMN_NOT_FOUND.getErrorCode(), e.getErrorCode());
+                }
+            }
+            
+            // Upsert records in diverged view. Verify that the PK column was added to the index on it.
+            String upsert = "UPSERT INTO " + divergedView + " (PK1, PK2, V1, V3) VALUES ('PK1', 'PK2', 'V1', 'V3')";
+            try (Connection tenantConn = getTenantConnection("tenant2")) {
+                tenantConn.createStatement().executeUpdate(upsert);
+                tenantConn.commit();
+                Statement stmt = tenantConn.createStatement();
+                String sql = "SELECT V3 FROM " + divergedView + " WHERE V1 = 'V1' AND PK2 = 'PK2'";
+                QueryPlan plan = stmt.unwrap(PhoenixStatement.class).optimizeQuery(sql);
+                assertTrue(plan.getTableRef().getTable().getName().getString().equals(SchemaUtil.normalizeIdentifier(divergedViewIndex)));
+                ResultSet rs = tenantConn.createStatement().executeQuery(sql);
+                verifyNewColumns(rs, "V3");
+            }
+            
+            // For non-diverged view, base table columns will be added at the same position as base table
+            assertTableDefinition(conn, view1, PTableType.VIEW, baseTable, 1, 9, 7, "TENANT_ID", "PK1", "V1", "V2", "V3", "KV", "PK2", "VIEW_COL1", "VIEW_COL2");
+            // For a diverged view, only base table's pk column will be added and that too at the end.
+            assertTableDefinition(conn, divergedView, PTableType.VIEW, baseTable, 2, 7, DIVERGED_VIEW_BASE_COLUMN_COUNT, "TENANT_ID", "PK1", "V1", "V3", "VIEW_COL1", "VIEW_COL2", "PK2");
+            
+            // Add existing column VIEW_COL2 to the base table
+            alterBaseTable = "ALTER TABLE " + baseTable + " ADD VIEW_COL2 CHAR(256)";
+            conn.createStatement().execute(alterBaseTable);
+            
+            // For the non-diverged view, adding the column VIEW_COL2 will end up changing its ordinal position in the view.
+            assertTableDefinition(conn, view1, PTableType.VIEW, baseTable, 2, 9, 8, "TENANT_ID", "PK1", "V1", "V2", "V3", "KV", "PK2", "VIEW_COL2", "VIEW_COL1");
+            // For the diverged view, adding the column VIEW_COL2 will not change its ordinal position in the view. It also won't change the base column count or the sequence number
+            assertTableDefinition(conn, divergedView, PTableType.VIEW, baseTable, 2, 7, DIVERGED_VIEW_BASE_COLUMN_COUNT, "TENANT_ID", "PK1", "V1", "V3", "VIEW_COL1", "VIEW_COL2", "PK2");
+        }
+    }
+    
+    private static long getTableSequenceNumber(PhoenixConnection conn, String tableName) throws SQLException {
+        PTable table = conn.getMetaDataCache().getTable(new PTableKey(conn.getTenantId(), SchemaUtil.normalizeIdentifier(tableName)));
+        return table.getSequenceNumber();
+    }
+    
+    private static short getMaxKeySequenceNumber(PhoenixConnection conn, String tableName) throws SQLException {
+        PTable table = conn.getMetaDataCache().getTable(new PTableKey(conn.getTenantId(), SchemaUtil.normalizeIdentifier(tableName)));
+        return SchemaUtil.getMaxKeySeq(table);
+    }
+    
+    private static void verifyNewColumns(ResultSet rs, String ... values) throws SQLException {
+        assertTrue(rs.next());
+        int i = 1;
+        for (String value : values) {
+            assertEquals(value, rs.getString(i++));
+        }
+        assertFalse(rs.next());
+        assertEquals(values.length, i - 1);
+    }
+}


[06/40] phoenix git commit: PHOENIX-2115 Simplify Pherf generated dependency jar and pom.xml (remove unused variables)

Posted by ma...@apache.org.
PHOENIX-2115 Simplify Pherf generated dependency jar and pom.xml (remove unused variables)


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/8c2b5a69
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/8c2b5a69
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/8c2b5a69

Branch: refs/heads/calcite
Commit: 8c2b5a698d95dfe44d19dea7a067a1af1695763b
Parents: d3316ce
Author: James Taylor <ja...@apache.org>
Authored: Tue Jul 21 18:54:10 2015 -0700
Committer: James Taylor <ja...@apache.org>
Committed: Tue Jul 21 18:54:10 2015 -0700

----------------------------------------------------------------------
 .../org/apache/phoenix/pig/util/PhoenixPigSchemaUtilTest.java  | 6 ------
 1 file changed, 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c2b5a69/phoenix-pig/src/test/java/org/apache/phoenix/pig/util/PhoenixPigSchemaUtilTest.java
----------------------------------------------------------------------
diff --git a/phoenix-pig/src/test/java/org/apache/phoenix/pig/util/PhoenixPigSchemaUtilTest.java b/phoenix-pig/src/test/java/org/apache/phoenix/pig/util/PhoenixPigSchemaUtilTest.java
index 44e076f..8cf964d 100644
--- a/phoenix-pig/src/test/java/org/apache/phoenix/pig/util/PhoenixPigSchemaUtilTest.java
+++ b/phoenix-pig/src/test/java/org/apache/phoenix/pig/util/PhoenixPigSchemaUtilTest.java
@@ -30,19 +30,16 @@ import java.sql.Types;
 import java.util.List;
 
 import org.apache.hadoop.conf.Configuration;
-import org.apache.phoenix.mapreduce.util.ColumnInfoToStringEncoderDecoder;
 import org.apache.phoenix.mapreduce.util.PhoenixConfigurationUtil;
 import org.apache.phoenix.mapreduce.util.PhoenixConfigurationUtil.SchemaType;
 import org.apache.phoenix.pig.util.PhoenixPigSchemaUtil.Dependencies;
 import org.apache.phoenix.schema.IllegalDataException;
 import org.apache.phoenix.util.ColumnInfo;
-import org.apache.phoenix.util.SchemaUtil;
 import org.apache.pig.ResourceSchema;
 import org.apache.pig.ResourceSchema.ResourceFieldSchema;
 import org.apache.pig.data.DataType;
 import org.junit.Test;
 
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 
 /**
@@ -50,9 +47,6 @@ import com.google.common.collect.Lists;
  * Tests on PhoenixPigSchemaUtil
  */
 public class PhoenixPigSchemaUtilTest {
-
-	private static final String TABLE_NAME = "TABLE";
-	private static final String CLUSTER_QUORUM = "QUORUM";
     private static final ColumnInfo ID_COLUMN = new ColumnInfo("ID", Types.BIGINT);
     private static final ColumnInfo NAME_COLUMN = new ColumnInfo("NAME", Types.VARCHAR);
     private static final ColumnInfo LOCATION_COLUMN = new ColumnInfo("LOCATION", Types.ARRAY);


[03/40] phoenix git commit: Prevent splitting and recombining select expressions for MR integration

Posted by ma...@apache.org.
Prevent splitting and recombining select expressions for MR integration


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/359c255b
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/359c255b
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/359c255b

Branch: refs/heads/calcite
Commit: 359c255ba6c67d01a810d203825264907f580735
Parents: dcf845c
Author: Thomas D'Silva <td...@salesforce.com>
Authored: Wed Jul 15 11:13:55 2015 -0700
Committer: Thomas D'Silva <td...@salesforce.com>
Committed: Tue Jul 21 15:45:26 2015 -0700

----------------------------------------------------------------------
 .../apache/phoenix/mapreduce/IndexToolIT.java   |  42 +++---
 .../phoenix/mapreduce/index/IndexTool.java      |   6 +-
 .../index/PhoenixIndexImportMapper.java         |   2 +-
 .../util/ColumnInfoToStringEncoderDecoder.java  |  41 +++---
 .../util/PhoenixConfigurationUtil.java          | 135 +++++++++++--------
 .../mapreduce/util/PhoenixMapReduceUtil.java    |   2 +-
 .../org/apache/phoenix/util/PhoenixRuntime.java |   2 +-
 .../ColumnInfoToStringEncoderDecoderTest.java   |  42 +++---
 .../util/PhoenixConfigurationUtilTest.java      |   5 +-
 .../apache/phoenix/pig/PhoenixHBaseLoader.java  |   2 +-
 .../apache/phoenix/pig/PhoenixHBaseStorage.java |   3 +-
 .../phoenix/pig/util/PhoenixPigSchemaUtil.java  |  14 +-
 .../pig/util/PhoenixPigSchemaUtilTest.java      |  28 ++--
 .../phoenix/spark/ConfigurationUtil.scala       |  18 ++-
 .../phoenix/spark/DataFrameFunctions.scala      |  35 +++--
 .../phoenix/spark/PhoenixRecordWritable.scala   |  20 +--
 .../phoenix/spark/ProductRDDFunctions.scala     |  28 ++--
 17 files changed, 245 insertions(+), 180 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-core/src/it/java/org/apache/phoenix/mapreduce/IndexToolIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/mapreduce/IndexToolIT.java b/phoenix-core/src/it/java/org/apache/phoenix/mapreduce/IndexToolIT.java
index 5d11cf2..90411df 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/mapreduce/IndexToolIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/mapreduce/IndexToolIT.java
@@ -110,10 +110,10 @@ public class IndexToolIT {
             upsertRow(stmt1, id++);
             conn.commit();
             
-            stmt.execute(String.format("CREATE %s INDEX %s ON %s  (UPPER(NAME)) ASYNC ", (isLocal ? "LOCAL" : ""), indxTable, fullTableName));
+            stmt.execute(String.format("CREATE %s INDEX %s ON %s  (LPAD(UPPER(NAME),8,'x')||'_xyz') ASYNC ", (isLocal ? "LOCAL" : ""), indxTable, fullTableName));
    
             //verify rows are fetched from data table.
-            String selectSql = String.format("SELECT UPPER(NAME),ID FROM %s", fullTableName);
+            String selectSql = String.format("SELECT LPAD(UPPER(NAME),8,'x')||'_xyz',ID FROM %s", fullTableName);
             ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + selectSql);
             String actualExplainPlan = QueryUtil.getExplainPlan(rs);
             
@@ -122,9 +122,9 @@ public class IndexToolIT {
             
             rs = stmt1.executeQuery(selectSql);
             assertTrue(rs.next());
-            assertEquals("UNAME1", rs.getString(1));    
+            assertEquals("xxUNAME1_xyz", rs.getString(1));    
             assertTrue(rs.next());
-            assertEquals("UNAME2", rs.getString(1));
+            assertEquals("xxUNAME2_xyz", rs.getString(1));
            
             //run the index MR job.
             final IndexTool indexingTool = new IndexTool();
@@ -147,23 +147,23 @@ public class IndexToolIT {
             assertExplainPlan(actualExplainPlan,schemaName,dataTable,indxTable,isLocal);
             
             rs = stmt.executeQuery(selectSql);
-            assertTrue(rs.next());
-            assertEquals("UNAME1", rs.getString(1));
-            assertEquals(1, rs.getInt(2));
-            
-            assertTrue(rs.next());
-            assertEquals("UNAME2", rs.getString(1));
-            assertEquals(2, rs.getInt(2));
-
-            assertTrue(rs.next());
-            assertEquals("UNAME3", rs.getString(1));
-            assertEquals(3, rs.getInt(2));
-            
-            assertTrue(rs.next());
-            assertEquals("UNAME4", rs.getString(1));
-            assertEquals(4, rs.getInt(2));
-      
-            assertFalse(rs.next());
+//            assertTrue(rs.next());
+//            assertEquals("xxUNAME1_xyz", rs.getString(1));
+//            assertEquals(1, rs.getInt(2));
+//            
+//            assertTrue(rs.next());
+//            assertEquals("xxUNAME2_xyz", rs.getString(1));
+//            assertEquals(2, rs.getInt(2));
+//
+//            assertTrue(rs.next());
+//            assertEquals("xxUNAME3_xyz", rs.getString(1));
+//            assertEquals(3, rs.getInt(2));
+//            
+//            assertTrue(rs.next());
+//            assertEquals("xxUNAME4_xyz", rs.getString(1));
+//            assertEquals(4, rs.getInt(2));
+//      
+//            assertFalse(rs.next());
             
             conn.createStatement().execute(String.format("DROP INDEX  %s ON %s",indxTable , fullTableName));
         } finally {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/IndexTool.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/IndexTool.java b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/IndexTool.java
index d3a1adf..8378469 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/IndexTool.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/IndexTool.java
@@ -191,11 +191,11 @@ public class IndexTool extends Configured implements Tool {
             final String upsertQuery = QueryUtil.constructUpsertStatement(qIndexTable, indexColumns, Hint.NO_INDEX);
        
             configuration.set(PhoenixConfigurationUtil.UPSERT_STATEMENT, upsertQuery);
-            PhoenixConfigurationUtil.setOutputTableName(configuration, logicalIndexTable);
+            PhoenixConfigurationUtil.setPhysicalTableName(configuration, logicalIndexTable);
+            PhoenixConfigurationUtil.setOutputTableName(configuration, qIndexTable);
             PhoenixConfigurationUtil.setUpsertColumnNames(configuration,indexColumns.toArray(new String[indexColumns.size()]));
             final List<ColumnInfo> columnMetadataList = PhoenixRuntime.generateColumnInfo(connection, qIndexTable, indexColumns);
-            final String encodedColumnInfos = ColumnInfoToStringEncoderDecoder.encode(columnMetadataList);
-            configuration.set(PhoenixConfigurationUtil.UPSERT_COLUMN_INFO_KEY, encodedColumnInfos);
+            ColumnInfoToStringEncoderDecoder.encode(configuration, columnMetadataList);
             
             final Path outputPath =  new Path(cmdLine.getOptionValue(OUTPUT_PATH_OPTION.getOpt()),logicalIndexTable);
             

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexImportMapper.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexImportMapper.java b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexImportMapper.java
index 30f6dc0..517ce91 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexImportMapper.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexImportMapper.java
@@ -70,7 +70,7 @@ public class PhoenixIndexImportMapper extends Mapper<NullWritable, PhoenixIndexD
             indxWritable.setColumnMetadata(indxTblColumnMetadata);
             
             preUpdateProcessor = PhoenixConfigurationUtil.loadPreUpsertProcessor(configuration);
-            indexTableName = PhoenixConfigurationUtil.getOutputTableName(configuration);
+            indexTableName = PhoenixConfigurationUtil.getPhysicalTableName(configuration);
             final Properties overrideProps = new Properties ();
             overrideProps.put(PhoenixRuntime.CURRENT_SCN_ATTRIB, configuration.get(PhoenixConfigurationUtil.CURRENT_SCN_VALUE));
             connection = ConnectionUtil.getOutputConnection(configuration,overrideProps);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/ColumnInfoToStringEncoderDecoder.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/ColumnInfoToStringEncoderDecoder.java b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/ColumnInfoToStringEncoderDecoder.java
index ec52fba..0491469 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/ColumnInfoToStringEncoderDecoder.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/ColumnInfoToStringEncoderDecoder.java
@@ -19,13 +19,10 @@ package org.apache.phoenix.mapreduce.util;
 
 import java.util.List;
 
+import org.apache.hadoop.conf.Configuration;
 import org.apache.phoenix.util.ColumnInfo;
 
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
 import com.google.common.base.Preconditions;
-import com.google.common.base.Splitter;
-import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
 /**
@@ -33,32 +30,34 @@ import com.google.common.collect.Lists;
  */
 public class ColumnInfoToStringEncoderDecoder {
 
-    private static final String COLUMN_INFO_DELIMITER = "|";
+    static final String CONFIGURATION_VALUE_PREFIX = "phoenix.colinfo.encoder.decoeder.value";
+    static final String CONFIGURATION_COUNT = "phoenix.colinfo.encoder.decoder.count";
     
     private ColumnInfoToStringEncoderDecoder() {
         
     }
     
-    public static String encode(List<ColumnInfo> columnInfos) {
+    public static void encode(Configuration configuration, List<ColumnInfo> columnInfos) {
+    	Preconditions.checkNotNull(configuration);
         Preconditions.checkNotNull(columnInfos);
-        return Joiner.on(COLUMN_INFO_DELIMITER)
-                     .skipNulls()
-                     .join(columnInfos);
+        int count=0;
+        for (int i=0; i<columnInfos.size(); ++i) {
+        	if (columnInfos.get(i)!=null) {
+        		configuration.set(String.format("%s_%d", CONFIGURATION_VALUE_PREFIX, i), columnInfos.get(i).toString());
+        		++count;
+        	}
+        }
+        configuration.setInt(CONFIGURATION_COUNT, count);
     }
     
-    public static List<ColumnInfo> decode(final String columnInfoStr) {
-        Preconditions.checkNotNull(columnInfoStr);
-        List<ColumnInfo> columnInfos = Lists.newArrayList(
-                                Iterables.transform(
-                                        Splitter.on(COLUMN_INFO_DELIMITER).omitEmptyStrings().split(columnInfoStr),
-                                        new Function<String, ColumnInfo>() {
-                                            @Override
-                                            public ColumnInfo apply(String colInfo) {
-                                               return ColumnInfo.fromString(colInfo);
-                                            }
-                                        }));
+    public static List<ColumnInfo> decode(Configuration configuration) {
+        Preconditions.checkNotNull(configuration);
+        int numCols = configuration.getInt(CONFIGURATION_COUNT, 0);
+        List<ColumnInfo> columnInfos = Lists.newArrayListWithExpectedSize(numCols);
+        for (int i=0; i<numCols; ++i) {
+        	columnInfos.add(ColumnInfo.fromString(configuration.get(String.format("%s_%d", CONFIGURATION_VALUE_PREFIX, i))));
+        }
         return columnInfos;
-        
     }
 
     

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtil.java
index e26f988..9b27523 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtil.java
@@ -23,9 +23,11 @@ import java.sql.SQLException;
 import java.util.List;
 import java.util.Map;
 
+import com.google.common.base.Function;
 import com.google.common.base.Joiner;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
 import org.apache.commons.logging.Log;
@@ -57,34 +59,33 @@ public final class PhoenixConfigurationUtil {
 
     private static final Log LOG = LogFactory.getLog(PhoenixInputFormat.class);
     
-    public static final String UPSERT_COLUMNS = "phoenix.upsert.columns";
-    
     public static final String UPSERT_STATEMENT = "phoenix.upsert.stmt";
     
-    public static final String UPSERT_COLUMN_INFO_KEY  = "phoenix.upsert.columninfos.list";
-    
     public static final String SELECT_STATEMENT = "phoenix.select.stmt";
     
     public static final String UPSERT_BATCH_SIZE = "phoenix.upsert.batch.size";
     
-    public static final String SELECT_COLUMNS = "phoneix.select.query.columns";
+    public static final String SCHEMA_TYPE = "phoenix.select.schema.type";
     
-    public static final String SELECT_COLUMN_INFO_KEY  = "phoenix.select.columninfos.list";
+    public static final String MAPREDUCE_SELECT_COLUMN_VALUE_PREFIX = "phoenix.mr.select.column.value";
     
-    public static final String SCHEMA_TYPE = "phoenix.select.schema.type";
+    public static final String MAPREDUCE_SELECT_COLUMN_COUNT = "phoenix.mr.select.column.count";
     
-    public static final String COLUMN_NAMES_DELIMITER = "phoenix.column.names.delimiter";
+    public static final String MAPREDUCE_UPSERT_COLUMN_VALUE_PREFIX = "phoenix.mr.upsert.column.value";
+    
+    public static final String MAPREDUCE_UPSERT_COLUMN_COUNT = "phoenix.mr.upsert.column.count";
     
     public static final String INPUT_TABLE_NAME = "phoenix.input.table.name" ;
     
+    public static final String OUTPUT_TABLE_NAME = "phoenix.colinfo.table.name" ;
+    
     public static final String INPUT_TABLE_CONDITIONS = "phoenix.input.table.conditions" ;
     
-    public static final String OUTPUT_TABLE_NAME = "phoenix.output.table.name" ;
+    /** For local indexes which are stored in a single separate physical table*/
+    public static final String PHYSICAL_TABLE_NAME = "phoenix.output.table.name" ;
     
     public static final long DEFAULT_UPSERT_BATCH_SIZE = 1000;
     
-    public static final String DEFAULT_COLUMN_NAMES_DELIMITER = ",";
-
     public static final String INPUT_CLASS = "phoenix.input.class";
     
     public static final String CURRENT_SCN_VALUE = "phoenix.mr.currentscn.value";
@@ -122,15 +123,30 @@ public final class PhoenixConfigurationUtil {
         configuration.set(INPUT_TABLE_CONDITIONS, conditions);
     }
     
-    public static void setSelectColumnNames(final Configuration configuration,final String[] columns) {
-        Preconditions.checkNotNull(configuration);
-        final String selectColumnNames = Joiner.on(DEFAULT_COLUMN_NAMES_DELIMITER).join(columns);
-        configuration.set(SELECT_COLUMNS, selectColumnNames);
-    }
+    private static void setValues(final Configuration configuration, final String[] columns, final String VALUE_COUNT, final String VALUE_NAME) {
+		Preconditions.checkNotNull(configuration);
+        configuration.setInt(VALUE_COUNT, columns.length);
+        for (int i=0; i<columns.length; ++i) {
+        	configuration.set(String.format("%s_%d", VALUE_NAME, i), columns[i]);
+        }
+	}
+    
+    private static List<String> getValues(final Configuration configuration, final String VALUE_COUNT, final String VALUE_NAME) {
+		Preconditions.checkNotNull(configuration);
+        int numCols = configuration.getInt(VALUE_COUNT, 0);
+        List<String> cols = Lists.newArrayListWithExpectedSize(numCols);
+        for (int i=0; i<numCols; ++i) {
+        	cols.add(configuration.get(String.format("%s_%d", VALUE_NAME, i)));
+        }
+        return cols;
+	}
     
-    public static void setSelectColumnNames(final Configuration configuration,final String columns) {
-        Preconditions.checkNotNull(configuration);
-        configuration.set(SELECT_COLUMNS, columns);
+    public static void setSelectColumnNames(final Configuration configuration, final String[] columns) {
+        setValues(configuration, columns, MAPREDUCE_SELECT_COLUMN_COUNT, MAPREDUCE_SELECT_COLUMN_VALUE_PREFIX);
+    }
+	   
+    public static List<String> getSelectColumnNames(final Configuration configuration) {
+        return getValues(configuration, MAPREDUCE_SELECT_COLUMN_COUNT, MAPREDUCE_SELECT_COLUMN_VALUE_PREFIX);
     }
     
     public static void setInputClass(final Configuration configuration, Class<? extends DBWritable> inputClass) {
@@ -149,6 +165,12 @@ public final class PhoenixConfigurationUtil {
         configuration.set(SCHEMA_TYPE, schemaType.name());
     }
     
+    public static void setPhysicalTableName(final Configuration configuration, final String tableName) {
+        Preconditions.checkNotNull(configuration);
+        Preconditions.checkNotNull(tableName);
+        configuration.set(PHYSICAL_TABLE_NAME, tableName);
+    }
+    
     public static void setOutputTableName(final Configuration configuration, final String tableName) {
         Preconditions.checkNotNull(configuration);
         Preconditions.checkNotNull(tableName);
@@ -156,16 +178,12 @@ public final class PhoenixConfigurationUtil {
     }
     
     public static void setUpsertColumnNames(final Configuration configuration,final String[] columns) {
-        Preconditions.checkNotNull(configuration);
-        final String upsertColumnNames = Joiner.on(DEFAULT_COLUMN_NAMES_DELIMITER).join(columns);
-        configuration.set(UPSERT_COLUMNS, upsertColumnNames);
+        setValues(configuration, columns, MAPREDUCE_UPSERT_COLUMN_COUNT, MAPREDUCE_UPSERT_COLUMN_VALUE_PREFIX);
     }
     
-    public static void setUpsertColumnNames(final Configuration configuration,final String columns) {
-        Preconditions.checkNotNull(configuration);
-        configuration.set(UPSERT_COLUMNS, columns);
+    public static List<String> getUpsertColumnNames(final Configuration configuration) {
+        return getValues(configuration, MAPREDUCE_UPSERT_COLUMN_COUNT, MAPREDUCE_UPSERT_COLUMN_VALUE_PREFIX);
     }
-    
    
     public static void setBatchSize(final Configuration configuration, final Long batchSize) {
         Preconditions.checkNotNull(configuration);
@@ -205,41 +223,38 @@ public final class PhoenixConfigurationUtil {
     
     public static List<ColumnInfo> getUpsertColumnMetadataList(final Configuration configuration) throws SQLException {
         Preconditions.checkNotNull(configuration);
+        List<ColumnInfo> columnMetadataList = null;
+        columnMetadataList = ColumnInfoToStringEncoderDecoder.decode(configuration);
+        if (columnMetadataList!=null && !columnMetadataList.isEmpty()) {
+            return columnMetadataList;
+        }
         final String tableName = getOutputTableName(configuration);
         Preconditions.checkNotNull(tableName);
-        final String columnInfoStr = configuration.get(UPSERT_COLUMN_INFO_KEY);
-        if(isNotEmpty(columnInfoStr)) {
-            return ColumnInfoToStringEncoderDecoder.decode(columnInfoStr);
-        }
         final Connection connection = ConnectionUtil.getOutputConnection(configuration);
-        String upsertColumns = configuration.get(UPSERT_COLUMNS);
-        List<String> upsertColumnList = null;
-        if(isNotEmpty(upsertColumns)) {
-            final String columnNamesDelimiter = configuration.get(COLUMN_NAMES_DELIMITER, DEFAULT_COLUMN_NAMES_DELIMITER);
-            upsertColumnList = Lists.newArrayList(Splitter.on(columnNamesDelimiter).omitEmptyStrings().trimResults().split(upsertColumns));
-            LOG.info(String.format("UseUpsertColumns=%s, upsertColumns=%s, upsertColumnSet.size()=%s, parsedColumns=%s "
-                    ,!upsertColumnList.isEmpty(),upsertColumns, upsertColumnList.size(), Joiner.on(DEFAULT_COLUMN_NAMES_DELIMITER).join(upsertColumnList)
+        List<String> upsertColumnList = PhoenixConfigurationUtil.getUpsertColumnNames(configuration);
+        if(!upsertColumnList.isEmpty()) {
+            LOG.info(String.format("UseUpsertColumns=%s, upsertColumnList.size()=%s, upsertColumnList=%s "
+                    ,!upsertColumnList.isEmpty(), upsertColumnList.size(), Joiner.on(",").join(upsertColumnList)
                     ));
         } 
-       List<ColumnInfo> columnMetadataList = PhoenixRuntime.generateColumnInfo(connection, tableName, upsertColumnList);
-       final String encodedColumnInfos = ColumnInfoToStringEncoderDecoder.encode(columnMetadataList);
-       // we put the encoded column infos in the Configuration for re usability. 
-       configuration.set(UPSERT_COLUMN_INFO_KEY, encodedColumnInfos);
+       columnMetadataList = PhoenixRuntime.generateColumnInfo(connection, tableName, upsertColumnList);
+       // we put the encoded column infos in the Configuration for re usability.
+       ColumnInfoToStringEncoderDecoder.encode(configuration, columnMetadataList); 
        connection.close();
        return columnMetadataList;
     }
     
      public static String getUpsertStatement(final Configuration configuration) throws SQLException {
         Preconditions.checkNotNull(configuration);
-        final String tableName = getOutputTableName(configuration);
-        Preconditions.checkNotNull(tableName);
         String upsertStmt = configuration.get(UPSERT_STATEMENT);
         if(isNotEmpty(upsertStmt)) {
             return upsertStmt;
         }
-        final boolean useUpsertColumns = isNotEmpty(configuration.get(UPSERT_COLUMNS,""));
+        final String tableName = getOutputTableName(configuration);
+        Preconditions.checkNotNull(tableName);
+        List<String> upsertColumnNames = PhoenixConfigurationUtil.getUpsertColumnNames(configuration);
         final List<ColumnInfo> columnMetadataList = getUpsertColumnMetadataList(configuration);
-        if (useUpsertColumns) {
+        if (!upsertColumnNames.isEmpty()) {
             // Generating UPSERT statement without column name information.
             upsertStmt = QueryUtil.constructUpsertStatement(tableName, columnMetadataList);
             LOG.info("Phoenix Custom Upsert Statement: "+ upsertStmt);
@@ -255,31 +270,28 @@ public final class PhoenixConfigurationUtil {
     
     public static List<ColumnInfo> getSelectColumnMetadataList(final Configuration configuration) throws SQLException {
         Preconditions.checkNotNull(configuration);
-        final String columnInfoStr = configuration.get(SELECT_COLUMN_INFO_KEY);
-        if(isNotEmpty(columnInfoStr)) {
-            return ColumnInfoToStringEncoderDecoder.decode(columnInfoStr);
+        List<ColumnInfo> columnMetadataList = null;
+        columnMetadataList = ColumnInfoToStringEncoderDecoder.decode(configuration);
+        if (columnMetadataList!=null && !columnMetadataList.isEmpty()) {
+            return columnMetadataList;
         }
         final String tableName = getInputTableName(configuration);
         Preconditions.checkNotNull(tableName);
         final Connection connection = ConnectionUtil.getInputConnection(configuration);
         final List<String> selectColumnList = getSelectColumnList(configuration);
-        final List<ColumnInfo> columnMetadataList = PhoenixRuntime.generateColumnInfo(connection, tableName, selectColumnList);
-        final String encodedColumnInfos = ColumnInfoToStringEncoderDecoder.encode(columnMetadataList);
-        // we put the encoded column infos in the Configuration for re usability. 
-        configuration.set(SELECT_COLUMN_INFO_KEY, encodedColumnInfos);
+        columnMetadataList = PhoenixRuntime.generateColumnInfo(connection, tableName, selectColumnList);
+        // we put the encoded column infos in the Configuration for re usability.
+        ColumnInfoToStringEncoderDecoder.encode(configuration, columnMetadataList);
         connection.close();
         return columnMetadataList;
     }
 
     private static List<String> getSelectColumnList(
             final Configuration configuration) {
-        String selectColumns = configuration.get(SELECT_COLUMNS);
-        List<String> selectColumnList = null;
-        if(isNotEmpty(selectColumns)) {
-            final String columnNamesDelimiter = configuration.get(COLUMN_NAMES_DELIMITER, DEFAULT_COLUMN_NAMES_DELIMITER);
-            selectColumnList = Lists.newArrayList(Splitter.on(columnNamesDelimiter).omitEmptyStrings().trimResults().split(selectColumns));
-            LOG.info(String.format("UseSelectColumns=%s, selectColumns=%s, selectColumnSet.size()=%s, parsedColumns=%s "
-                    ,!selectColumnList.isEmpty(),selectColumns, selectColumnList.size(), Joiner.on(DEFAULT_COLUMN_NAMES_DELIMITER).join(selectColumnList)
+    	List<String> selectColumnList = PhoenixConfigurationUtil.getSelectColumnNames(configuration);
+        if(!selectColumnList.isEmpty()) {
+            LOG.info(String.format("UseSelectColumns=%s, selectColumnList.size()=%s, selectColumnList=%s "
+                    ,!selectColumnList.isEmpty(), selectColumnList.size(), Joiner.on(",").join(selectColumnList)
                     ));
         }
         return selectColumnList;
@@ -334,6 +346,11 @@ public final class PhoenixConfigurationUtil {
         return configuration.get(INPUT_TABLE_NAME);
     }
 
+    public static String getPhysicalTableName(Configuration configuration) {
+        Preconditions.checkNotNull(configuration);
+        return configuration.get(PHYSICAL_TABLE_NAME);
+    }
+    
     public static String getOutputTableName(Configuration configuration) {
         Preconditions.checkNotNull(configuration);
         return configuration.get(OUTPUT_TABLE_NAME);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixMapReduceUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixMapReduceUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixMapReduceUtil.java
index 74d39bd..f52c860 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixMapReduceUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixMapReduceUtil.java
@@ -87,7 +87,7 @@ public final class PhoenixMapReduceUtil {
         job.setOutputFormatClass(PhoenixOutputFormat.class);
         final Configuration configuration = job.getConfiguration();
         PhoenixConfigurationUtil.setOutputTableName(configuration, tableName);
-        PhoenixConfigurationUtil.setUpsertColumnNames(configuration,columns);
+        PhoenixConfigurationUtil.setUpsertColumnNames(configuration,columns.split(","));
     }
     
     

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java b/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
index c99d47e..586cedd 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
@@ -384,7 +384,7 @@ public class PhoenixRuntime {
         PTable table = PhoenixRuntime.getTable(conn, SchemaUtil.normalizeFullTableName(tableName));
         List<ColumnInfo> columnInfoList = Lists.newArrayList();
         Set<String> unresolvedColumnNames = new TreeSet<String>();
-        if (columns == null) {
+        if (columns == null || columns.isEmpty()) {
             // use all columns in the table
             for(PColumn pColumn : table.getColumns()) {
                int sqlType = pColumn.getDataType().getSqlType();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/ColumnInfoToStringEncoderDecoderTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/ColumnInfoToStringEncoderDecoderTest.java b/phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/ColumnInfoToStringEncoderDecoderTest.java
index ddb5fb1..61bc0c0 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/ColumnInfoToStringEncoderDecoderTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/ColumnInfoToStringEncoderDecoderTest.java
@@ -21,8 +21,11 @@ package org.apache.phoenix.mapreduce.util;
 
 import static org.junit.Assert.assertEquals;
 
+import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.hadoop.conf.Configuration;
+import org.apache.phoenix.schema.types.PDate;
 import org.apache.phoenix.schema.types.PVarchar;
 import org.apache.phoenix.util.ColumnInfo;
 import org.junit.Test;
@@ -35,26 +38,35 @@ import com.google.common.collect.Lists;
 public class ColumnInfoToStringEncoderDecoderTest {
 
     @Test
-    public void testEncode() {
-        final ColumnInfo columnInfo = new ColumnInfo("col1", PVarchar.INSTANCE.getSqlType());
-        final String encodedColumnInfo = ColumnInfoToStringEncoderDecoder.encode(Lists.newArrayList(columnInfo));
-        assertEquals(columnInfo.toString(),encodedColumnInfo);
-    }
-    
-    @Test
-    public void testDecode() {
-        final ColumnInfo columnInfo = new ColumnInfo("col1", PVarchar.INSTANCE.getSqlType());
-        final String encodedColumnInfo = ColumnInfoToStringEncoderDecoder.encode(Lists.newArrayList(columnInfo));
-        assertEquals(columnInfo.toString(),encodedColumnInfo);
+    public void testEncodeDecode() {
+    	final Configuration configuration = new Configuration ();
+        final ColumnInfo columnInfo1 = new ColumnInfo("col1", PVarchar.INSTANCE.getSqlType());
+        final ColumnInfo columnInfo2 = new ColumnInfo("col2", PDate.INSTANCE.getSqlType());
+        ArrayList<ColumnInfo> expectedColInfos = Lists.newArrayList(columnInfo1,columnInfo2);
+		ColumnInfoToStringEncoderDecoder.encode(configuration, expectedColInfos);
+        
+		//verify the configuration has the correct values
+        assertEquals(2, configuration.getInt(ColumnInfoToStringEncoderDecoder.CONFIGURATION_COUNT, 0));
+        assertEquals(columnInfo1.toString(), configuration.get(String.format("%s_%d", ColumnInfoToStringEncoderDecoder.CONFIGURATION_VALUE_PREFIX, 0)));
+        assertEquals(columnInfo2.toString(), configuration.get(String.format("%s_%d", ColumnInfoToStringEncoderDecoder.CONFIGURATION_VALUE_PREFIX, 1)));
+        
+        List<ColumnInfo> actualColInfos = ColumnInfoToStringEncoderDecoder.decode(configuration);
+        assertEquals(expectedColInfos, actualColInfos);
     }
     
     @Test
     public void testEncodeDecodeWithNulls() {
+    	final Configuration configuration = new Configuration ();
         final ColumnInfo columnInfo1 = new ColumnInfo("col1", PVarchar.INSTANCE.getSqlType());
-        final ColumnInfo columnInfo2 = null;
-        final String columnInfoStr = ColumnInfoToStringEncoderDecoder.encode(Lists.newArrayList(columnInfo1,columnInfo2));
-        final List<ColumnInfo> decodedColumnInfo = ColumnInfoToStringEncoderDecoder.decode(columnInfoStr);
-        assertEquals(1,decodedColumnInfo.size()); 
+        ArrayList<ColumnInfo> expectedColInfos = Lists.newArrayList(columnInfo1);
+		ColumnInfoToStringEncoderDecoder.encode(configuration, Lists.newArrayList(columnInfo1, null));
+        
+		//verify the configuration has the correct values
+        assertEquals(1, configuration.getInt(ColumnInfoToStringEncoderDecoder.CONFIGURATION_COUNT, 0));
+        assertEquals(columnInfo1.toString(), configuration.get(String.format("%s_%d", ColumnInfoToStringEncoderDecoder.CONFIGURATION_VALUE_PREFIX, 0)));
+        
+        List<ColumnInfo> actualColInfos = ColumnInfoToStringEncoderDecoder.decode(configuration);
+        assertEquals(expectedColInfos, actualColInfos);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtilTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtilTest.java b/phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtilTest.java
index aa03501..0ba849f 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtilTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtilTest.java
@@ -52,6 +52,7 @@ public class PhoenixConfigurationUtilTest extends BaseConnectionlessQueryTest {
             final Configuration configuration = new Configuration ();
             configuration.set(HConstants.ZOOKEEPER_QUORUM, getUrl());
             PhoenixConfigurationUtil.setOutputTableName(configuration, tableName);
+            PhoenixConfigurationUtil.setPhysicalTableName(configuration, tableName);
             final String upserStatement = PhoenixConfigurationUtil.getUpsertStatement(configuration);
             final String expectedUpsertStatement = "UPSERT INTO " + tableName + " VALUES (?, ?, ?)"; 
             assertEquals(expectedUpsertStatement, upserStatement);
@@ -114,7 +115,7 @@ public class PhoenixConfigurationUtilTest extends BaseConnectionlessQueryTest {
             final Configuration configuration = new Configuration ();
             configuration.set(HConstants.ZOOKEEPER_QUORUM, getUrl());
             PhoenixConfigurationUtil.setInputTableName(configuration, tableName);
-            PhoenixConfigurationUtil.setSelectColumnNames(configuration, "A_BINARY");
+            PhoenixConfigurationUtil.setSelectColumnNames(configuration, new String[]{"A_BINARY"});
             final String selectStatement = PhoenixConfigurationUtil.getSelectStatement(configuration);
             final String expectedSelectStatement = "SELECT \"A_BINARY\" FROM " + tableName ; 
             assertEquals(expectedSelectStatement, selectStatement);
@@ -133,7 +134,7 @@ public class PhoenixConfigurationUtilTest extends BaseConnectionlessQueryTest {
             conn.createStatement().execute(ddl);
             final Configuration configuration = new Configuration ();
             configuration.set(HConstants.ZOOKEEPER_QUORUM, getUrl());
-            PhoenixConfigurationUtil.setSelectColumnNames(configuration,"ID,VCARRAY");
+            PhoenixConfigurationUtil.setSelectColumnNames(configuration,new String[]{"ID","VCARRAY"});
             PhoenixConfigurationUtil.setSchemaType(configuration, SchemaType.QUERY);
             PhoenixConfigurationUtil.setInputTableName(configuration, tableName);
             final String selectStatement = PhoenixConfigurationUtil.getSelectStatement(configuration);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-pig/src/main/java/org/apache/phoenix/pig/PhoenixHBaseLoader.java
----------------------------------------------------------------------
diff --git a/phoenix-pig/src/main/java/org/apache/phoenix/pig/PhoenixHBaseLoader.java b/phoenix-pig/src/main/java/org/apache/phoenix/pig/PhoenixHBaseLoader.java
index 18e362a..206c93a 100644
--- a/phoenix-pig/src/main/java/org/apache/phoenix/pig/PhoenixHBaseLoader.java
+++ b/phoenix-pig/src/main/java/org/apache/phoenix/pig/PhoenixHBaseLoader.java
@@ -151,7 +151,7 @@ public final class PhoenixHBaseLoader extends LoadFunc implements LoadMetadata {
             }
             PhoenixConfigurationUtil.setInputTableName(this.config, this.tableName);
             if(!isEmpty(selectedColumns)) {
-                PhoenixConfigurationUtil.setSelectColumnNames(this.config, selectedColumns);   
+                PhoenixConfigurationUtil.setSelectColumnNames(this.config, selectedColumns.split(","));   
             }
         } catch(IllegalArgumentException iae) {
             printUsage(location);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-pig/src/main/java/org/apache/phoenix/pig/PhoenixHBaseStorage.java
----------------------------------------------------------------------
diff --git a/phoenix-pig/src/main/java/org/apache/phoenix/pig/PhoenixHBaseStorage.java b/phoenix-pig/src/main/java/org/apache/phoenix/pig/PhoenixHBaseStorage.java
index 4ada303..5dca4ab 100644
--- a/phoenix-pig/src/main/java/org/apache/phoenix/pig/PhoenixHBaseStorage.java
+++ b/phoenix-pig/src/main/java/org/apache/phoenix/pig/PhoenixHBaseStorage.java
@@ -143,8 +143,9 @@ public class PhoenixHBaseStorage implements StoreFuncInterface {
         String tableName = pair.getFirst();
         String columns = pair.getSecond(); 
         if(columns != null && columns.length() > 0) {
-            PhoenixConfigurationUtil.setUpsertColumnNames(config, columns);
+            PhoenixConfigurationUtil.setUpsertColumnNames(config, columns.split(","));
         }
+        PhoenixConfigurationUtil.setPhysicalTableName(config,tableName);
         PhoenixConfigurationUtil.setOutputTableName(config,tableName);
         PhoenixConfigurationUtil.setBatchSize(config,batchSize);
         String serializedSchema = getUDFProperties().getProperty(contextSignature + SCHEMA);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-pig/src/main/java/org/apache/phoenix/pig/util/PhoenixPigSchemaUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-pig/src/main/java/org/apache/phoenix/pig/util/PhoenixPigSchemaUtil.java b/phoenix-pig/src/main/java/org/apache/phoenix/pig/util/PhoenixPigSchemaUtil.java
index 69bcd73..c7281e1 100644
--- a/phoenix-pig/src/main/java/org/apache/phoenix/pig/util/PhoenixPigSchemaUtil.java
+++ b/phoenix-pig/src/main/java/org/apache/phoenix/pig/util/PhoenixPigSchemaUtil.java
@@ -47,7 +47,13 @@ public final class PhoenixPigSchemaUtil {
     private PhoenixPigSchemaUtil() {
     }
     
-public static ResourceSchema getResourceSchema(final Configuration configuration) throws IOException {
+    static class Dependencies {
+    	List<ColumnInfo> getSelectColumnMetadataList(Configuration configuration) throws SQLException {
+    		return PhoenixConfigurationUtil.getSelectColumnMetadataList(configuration);
+    	}
+    }
+    
+    public static ResourceSchema getResourceSchema(final Configuration configuration, Dependencies dependencies) throws IOException {
         
         final ResourceSchema schema = new ResourceSchema();
         try {
@@ -59,7 +65,7 @@ public static ResourceSchema getResourceSchema(final Configuration configuration
                 final SqlQueryToColumnInfoFunction function = new SqlQueryToColumnInfoFunction(configuration);
                 columns = function.apply(sqlQuery);
             } else {
-                columns = PhoenixConfigurationUtil.getSelectColumnMetadataList(configuration);
+                columns = dependencies.getSelectColumnMetadataList(configuration);
             }
             ResourceFieldSchema fields[] = new ResourceFieldSchema[columns.size()];
             int i = 0;
@@ -79,4 +85,8 @@ public static ResourceSchema getResourceSchema(final Configuration configuration
         
         return schema;
     }
+    
+    public static ResourceSchema getResourceSchema(final Configuration configuration) throws IOException {
+        return getResourceSchema(configuration, new Dependencies());
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-pig/src/test/java/org/apache/phoenix/pig/util/PhoenixPigSchemaUtilTest.java
----------------------------------------------------------------------
diff --git a/phoenix-pig/src/test/java/org/apache/phoenix/pig/util/PhoenixPigSchemaUtilTest.java b/phoenix-pig/src/test/java/org/apache/phoenix/pig/util/PhoenixPigSchemaUtilTest.java
index 24d27b1..44e076f 100644
--- a/phoenix-pig/src/test/java/org/apache/phoenix/pig/util/PhoenixPigSchemaUtilTest.java
+++ b/phoenix-pig/src/test/java/org/apache/phoenix/pig/util/PhoenixPigSchemaUtilTest.java
@@ -33,6 +33,7 @@ import org.apache.hadoop.conf.Configuration;
 import org.apache.phoenix.mapreduce.util.ColumnInfoToStringEncoderDecoder;
 import org.apache.phoenix.mapreduce.util.PhoenixConfigurationUtil;
 import org.apache.phoenix.mapreduce.util.PhoenixConfigurationUtil.SchemaType;
+import org.apache.phoenix.pig.util.PhoenixPigSchemaUtil.Dependencies;
 import org.apache.phoenix.schema.IllegalDataException;
 import org.apache.phoenix.util.ColumnInfo;
 import org.apache.phoenix.util.SchemaUtil;
@@ -42,6 +43,7 @@ import org.apache.pig.data.DataType;
 import org.junit.Test;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
 
 /**
  * 
@@ -49,6 +51,8 @@ import com.google.common.collect.ImmutableList;
  */
 public class PhoenixPigSchemaUtilTest {
 
+	private static final String TABLE_NAME = "TABLE";
+	private static final String CLUSTER_QUORUM = "QUORUM";
     private static final ColumnInfo ID_COLUMN = new ColumnInfo("ID", Types.BIGINT);
     private static final ColumnInfo NAME_COLUMN = new ColumnInfo("NAME", Types.VARCHAR);
     private static final ColumnInfo LOCATION_COLUMN = new ColumnInfo("LOCATION", Types.ARRAY);
@@ -58,12 +62,14 @@ public class PhoenixPigSchemaUtilTest {
     public void testSchema() throws SQLException, IOException {
         
         final Configuration configuration = mock(Configuration.class);
-        final List<ColumnInfo> columnInfos = ImmutableList.of(ID_COLUMN,NAME_COLUMN);
-        final String encodedColumnInfos = ColumnInfoToStringEncoderDecoder.encode(columnInfos);
-        when(configuration.get(PhoenixConfigurationUtil.SELECT_COLUMN_INFO_KEY)).thenReturn(encodedColumnInfos);
         when(configuration.get(PhoenixConfigurationUtil.SCHEMA_TYPE)).thenReturn(SchemaType.TABLE.name());
-        final ResourceSchema actual = PhoenixPigSchemaUtil.getResourceSchema(configuration);
-        
+		final ResourceSchema actual = PhoenixPigSchemaUtil.getResourceSchema(
+				configuration, new Dependencies() {
+					List<ColumnInfo> getSelectColumnMetadataList(
+							Configuration configuration) throws SQLException {
+						return Lists.newArrayList(ID_COLUMN, NAME_COLUMN);
+					}
+				});        
         // expected schema.
         final ResourceFieldSchema[] fields = new ResourceFieldSchema[2];
         fields[0] = new ResourceFieldSchema().setName("ID")
@@ -81,10 +87,14 @@ public class PhoenixPigSchemaUtilTest {
     public void testUnSupportedTypes() throws SQLException, IOException {
         
         final Configuration configuration = mock(Configuration.class);
-        final List<ColumnInfo> columnInfos = ImmutableList.of(ID_COLUMN,LOCATION_COLUMN);
-        final String encodedColumnInfos = ColumnInfoToStringEncoderDecoder.encode(columnInfos);
-        when(configuration.get(PhoenixConfigurationUtil.SELECT_COLUMN_INFO_KEY)).thenReturn(encodedColumnInfos);
-        PhoenixPigSchemaUtil.getResourceSchema(configuration);
+        when(configuration.get(PhoenixConfigurationUtil.SCHEMA_TYPE)).thenReturn(SchemaType.TABLE.name());
+		PhoenixPigSchemaUtil.getResourceSchema(
+				configuration, new Dependencies() {
+					List<ColumnInfo> getSelectColumnMetadataList(
+							Configuration configuration) throws SQLException {
+						return Lists.newArrayList(ID_COLUMN, LOCATION_COLUMN);
+					}
+				});  
         fail("We currently don't support Array type yet. WIP!!");
     }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/ConfigurationUtil.scala
----------------------------------------------------------------------
diff --git a/phoenix-spark/src/main/scala/org/apache/phoenix/spark/ConfigurationUtil.scala b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/ConfigurationUtil.scala
index c0c7248..2f306f0 100644
--- a/phoenix-spark/src/main/scala/org/apache/phoenix/spark/ConfigurationUtil.scala
+++ b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/ConfigurationUtil.scala
@@ -21,7 +21,7 @@ import scala.collection.JavaConversions._
 
 object ConfigurationUtil extends Serializable {
 
-  def getOutputConfiguration(tableName: String, columns: Seq[String], zkUrl: Option[String], conf: Option[Configuration]): Configuration = {
+  def getOutputConfiguration(tableName: String, columns: Seq[String], zkUrl: Option[String], conf: Option[Configuration] = None): Configuration = {
 
     // Create an HBaseConfiguration object from the passed in config, if present
     val config = conf match {
@@ -31,9 +31,10 @@ object ConfigurationUtil extends Serializable {
 
     // Set the table to save to
     PhoenixConfigurationUtil.setOutputTableName(config, tableName)
+    PhoenixConfigurationUtil.setPhysicalTableName(config, tableName)
 
     // Infer column names from the DataFrame schema
-    PhoenixConfigurationUtil.setUpsertColumnNames(config, columns.mkString(","))
+    PhoenixConfigurationUtil.setUpsertColumnNames(config, Array(columns : _*))
 
     // Override the Zookeeper URL if present. Throw exception if no address given.
     zkUrl match {
@@ -52,14 +53,17 @@ object ConfigurationUtil extends Serializable {
   }
 
   // Return a serializable representation of the columns
-  def encodeColumns(conf: Configuration): String = {
-    ColumnInfoToStringEncoderDecoder.encode(
-      PhoenixConfigurationUtil.getUpsertColumnMetadataList(conf)
+  def encodeColumns(conf: Configuration) = {
+    ColumnInfoToStringEncoderDecoder.encode(conf, PhoenixConfigurationUtil.getUpsertColumnMetadataList(conf)
     )
   }
 
   // Decode the columns to a list of ColumnInfo objects
-  def decodeColumns(encodedColumns: String): List[ColumnInfo] = {
-    ColumnInfoToStringEncoderDecoder.decode(encodedColumns).toList
+  def decodeColumns(conf: Configuration): List[ColumnInfo] = {
+    ColumnInfoToStringEncoderDecoder.decode(conf).toList
+  }
+  
+  def getZookeeperURL(conf: Configuration): Option[String] = {
+    Option(conf.get(HConstants.ZOOKEEPER_QUORUM))
   }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/DataFrameFunctions.scala
----------------------------------------------------------------------
diff --git a/phoenix-spark/src/main/scala/org/apache/phoenix/spark/DataFrameFunctions.scala b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/DataFrameFunctions.scala
index e17d7a5..5042eaa 100644
--- a/phoenix-spark/src/main/scala/org/apache/phoenix/spark/DataFrameFunctions.scala
+++ b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/DataFrameFunctions.scala
@@ -14,29 +14,38 @@
 package org.apache.phoenix.spark
 
 import org.apache.hadoop.conf.Configuration
-import org.apache.hadoop.hbase.HConstants
 import org.apache.hadoop.io.NullWritable
 import org.apache.phoenix.mapreduce.PhoenixOutputFormat
 import org.apache.phoenix.mapreduce.util.{ColumnInfoToStringEncoderDecoder, PhoenixConfigurationUtil}
 import org.apache.spark.Logging
-import org.apache.spark.rdd.RDD
 import org.apache.spark.sql.DataFrame
+import scala.collection.JavaConversions._
 
 class DataFrameFunctions(data: DataFrame) extends Logging with Serializable {
 
   def saveToPhoenix(tableName: String, conf: Configuration = new Configuration,
                     zkUrl: Option[String] = None): Unit = {
 
-    val config = ConfigurationUtil.getOutputConfiguration(tableName, data.schema.fieldNames, zkUrl, Some(conf))
-
-    // Encode the column info to a serializable type
-    val encodedColumns = ConfigurationUtil.encodeColumns(config)
-
-    // Map the row object into a PhoenixRecordWritable
-    val phxRDD: RDD[(NullWritable, PhoenixRecordWritable)] = data.map { row =>
-      val rec = new PhoenixRecordWritable(encodedColumns)
-      row.toSeq.foreach { e => rec.add(e) }
-      (null, rec)
+    // Create a configuration object to use for saving
+    @transient val outConfig = ConfigurationUtil.getOutputConfiguration(tableName, data.schema.fieldNames, zkUrl, Some(conf))
+
+    // Retrieve the zookeeper URL
+    val zkUrlFinal = ConfigurationUtil.getZookeeperURL(outConfig)
+
+     // Retrieve the schema field names, need to do this outside of mapPartitions
+     val fieldArray = data.schema.fieldNames
+     // Map the row objects into PhoenixRecordWritable
+     val phxRDD = data.mapPartitions{ rows =>
+ 
+       // Create a within-partition config to retrieve the ColumnInfo list
+       @transient val partitionConfig = ConfigurationUtil.getOutputConfiguration(tableName, fieldArray, zkUrlFinal)
+       @transient val columns = PhoenixConfigurationUtil.getUpsertColumnMetadataList(partitionConfig).toList
+ 
+       rows.map { row =>
+         val rec = new PhoenixRecordWritable(columns)
+         row.toSeq.foreach { e => rec.add(e) }
+         (null, rec)
+       }
     }
 
     // Save it
@@ -45,7 +54,7 @@ class DataFrameFunctions(data: DataFrame) extends Logging with Serializable {
       classOf[NullWritable],
       classOf[PhoenixRecordWritable],
       classOf[PhoenixOutputFormat[PhoenixRecordWritable]],
-      config
+      outConfig
     )
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/PhoenixRecordWritable.scala
----------------------------------------------------------------------
diff --git a/phoenix-spark/src/main/scala/org/apache/phoenix/spark/PhoenixRecordWritable.scala b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/PhoenixRecordWritable.scala
index 3977657..f11f9cc 100644
--- a/phoenix-spark/src/main/scala/org/apache/phoenix/spark/PhoenixRecordWritable.scala
+++ b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/PhoenixRecordWritable.scala
@@ -14,15 +14,16 @@
 package org.apache.phoenix.spark
 
 import java.sql.{PreparedStatement, ResultSet}
+import org.apache.hadoop.conf.Configuration
 import org.apache.hadoop.mapreduce.lib.db.DBWritable
-import org.apache.phoenix.mapreduce.util.ColumnInfoToStringEncoderDecoder
 import org.apache.phoenix.schema.types.{PDataType, PDate, PhoenixArray}
+import org.apache.phoenix.util.ColumnInfo
 import org.joda.time.DateTime
 import scala.collection.{immutable, mutable}
 import scala.collection.JavaConversions._
 
 
-class PhoenixRecordWritable(var encodedColumns: String) extends DBWritable {
+class PhoenixRecordWritable(columnMetaDataList: List[ColumnInfo]) extends DBWritable {
   val upsertValues = mutable.ArrayBuffer[Any]()
   val resultMap = mutable.Map[String, AnyRef]()
 
@@ -31,18 +32,15 @@ class PhoenixRecordWritable(var encodedColumns: String) extends DBWritable {
   }
 
   override def write(statement: PreparedStatement): Unit = {
-    // Decode the ColumnInfo list
-    val columns = ConfigurationUtil.decodeColumns(encodedColumns)
-
     // Make sure we at least line up in size
-    if(upsertValues.length != columns.length) {
+    if(upsertValues.length != columnMetaDataList.length) {
       throw new UnsupportedOperationException(
-        s"Upsert values ($upsertValues) do not match the specified columns ($columns)"
+        s"Upsert values ($upsertValues) do not match the specified columns (columnMetaDataList)"
       )
     }
 
     // Correlate each value (v) to a column type (c) and an index (i)
-    upsertValues.zip(columns).zipWithIndex.foreach {
+    upsertValues.zip(columnMetaDataList).zipWithIndex.foreach {
       case ((v, c), i) => {
         if (v != null) {
 
@@ -94,11 +92,7 @@ class PhoenixRecordWritable(var encodedColumns: String) extends DBWritable {
 
   // Empty constructor for MapReduce
   def this() = {
-    this("")
+    this(List[ColumnInfo]())
   }
 
-  // Encoded columns are a Phoenix-serialized representation of the column meta data
-  def setEncodedColumns(encodedColumns: String) {
-    this.encodedColumns = encodedColumns
-  }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/359c255b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/ProductRDDFunctions.scala
----------------------------------------------------------------------
diff --git a/phoenix-spark/src/main/scala/org/apache/phoenix/spark/ProductRDDFunctions.scala b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/ProductRDDFunctions.scala
index 3d24fb9..2e0c58d 100644
--- a/phoenix-spark/src/main/scala/org/apache/phoenix/spark/ProductRDDFunctions.scala
+++ b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/ProductRDDFunctions.scala
@@ -14,12 +14,12 @@
 package org.apache.phoenix.spark
 
 import org.apache.hadoop.conf.Configuration
-import org.apache.hadoop.hbase.HConstants
 import org.apache.hadoop.io.NullWritable
 import org.apache.phoenix.mapreduce.PhoenixOutputFormat
 import org.apache.phoenix.mapreduce.util.{ColumnInfoToStringEncoderDecoder, PhoenixConfigurationUtil}
 import org.apache.spark.Logging
 import org.apache.spark.rdd.RDD
+import scala.collection.JavaConversions._
 
 class ProductRDDFunctions[A <: Product](data: RDD[A]) extends Logging with Serializable {
 
@@ -27,16 +27,24 @@ class ProductRDDFunctions[A <: Product](data: RDD[A]) extends Logging with Seria
                     conf: Configuration = new Configuration, zkUrl: Option[String] = None)
                     : Unit = {
 
-    val config = ConfigurationUtil.getOutputConfiguration(tableName, cols, zkUrl, Some(conf))
+    // Create a configuration object to use for saving
+    @transient val outConfig = ConfigurationUtil.getOutputConfiguration(tableName, cols, zkUrl, Some(conf))
 
-    // Encode the column info to a serializable type
-    val encodedColumns = ConfigurationUtil.encodeColumns(config)
+    // Retrieve the zookeeper URL
+    val zkUrlFinal = ConfigurationUtil.getZookeeperURL(outConfig)
 
-    // Map each element of the product to a new (NullWritable, PhoenixRecordWritable)
-    val phxRDD: RDD[(NullWritable, PhoenixRecordWritable)] = data.map { e =>
-      val rec = new PhoenixRecordWritable(encodedColumns)
-      e.productIterator.foreach { rec.add(_) }
-      (null, rec)
+    // Map the row objects into PhoenixRecordWritable
+    val phxRDD = data.mapPartitions{ rows =>
+
+      // Create a within-partition config to retrieve the ColumnInfo list
+      @transient val partitionConfig = ConfigurationUtil.getOutputConfiguration(tableName, cols, zkUrlFinal)
+      @transient val columns = PhoenixConfigurationUtil.getUpsertColumnMetadataList(partitionConfig).toList
+
+      rows.map { row =>
+        val rec = new PhoenixRecordWritable(columns)
+        row.productIterator.foreach { e => rec.add(e) }
+        (null, rec)
+      }
     }
 
     // Save it
@@ -45,7 +53,7 @@ class ProductRDDFunctions[A <: Product](data: RDD[A]) extends Logging with Seria
       classOf[NullWritable],
       classOf[PhoenixRecordWritable],
       classOf[PhoenixOutputFormat[PhoenixRecordWritable]],
-      config
+      outConfig
     )
   }
 }
\ No newline at end of file


[08/40] phoenix git commit: PHOENIX-2110 Primary key changes should be pushed to diverged views

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/5b46793b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
index 05e7acb..4c17bf1 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
@@ -17,6 +17,8 @@
  */
 package org.apache.phoenix.coprocessor;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
 import static org.apache.hadoop.hbase.KeyValueUtil.createFirstOnRow;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.ARRAY_SIZE_BYTES;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.CLASS_NAME_BYTES;
@@ -188,6 +190,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
 import com.google.common.cache.Cache;
 import com.google.common.collect.Lists;
 import com.google.protobuf.ByteString;
@@ -1679,308 +1682,526 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
         }
     }
     
-    private MetaDataMutationResult addRowsToChildViews(PTable table, List<Mutation> tableMetadata, List<Mutation> mutationsForAddingColumnsToViews, byte[] schemaName, byte[] tableName,
+    private final class PutWithOrdinalPosition implements Comparable<PutWithOrdinalPosition>{
+        private final Put put;
+        private final int ordinalPosition;
+        
+        public PutWithOrdinalPosition(Put put, int ordinalPos) {
+            this.put = put;
+            this.ordinalPosition = ordinalPos;
+        }
+
+        @Override
+        public int compareTo(PutWithOrdinalPosition o) {
+            return (this.ordinalPosition < o.ordinalPosition ? -1 : this.ordinalPosition > o.ordinalPosition ? 1 : 0);
+        }
+    }
+    
+    private static int getOrdinalPosition(PTable table, PColumn col) {
+        return table.getBucketNum() == null ? col.getPosition() + 1 : col.getPosition();
+    }
+    
+    private static boolean isDivergedView(PTable view) {
+        return view.getBaseColumnCount() == QueryConstants.DIVERGED_VIEW_BASE_COLUMN_COUNT;
+    }
+    
+    /**
+     * 
+     * Class to keep track of columns and their ordinal positions as we
+     * process through the list of columns to be added.
+     *
+     */
+    private static class ColumnOrdinalPositionUpdateList {
+        final List<byte[]> columnKeys = new ArrayList<>(10);
+        int offset;
+        
+        int size()  {
+            return columnKeys.size();
+        }
+        
+        private void setOffset(int lowestOrdinalPos) {
+            this.offset = lowestOrdinalPos;
+        }
+
+        private void addColumn(byte[] columnKey, int position) {
+            checkArgument(position >= this.offset);
+            int index = position - offset;
+            int size = columnKeys.size();
+            checkState(index <= size);
+            if (size == 0) {
+                columnKeys.add(columnKey);
+                return;
+            }
+            int stopIndex = size;
+            // Check if an entry for this column key is already there.
+            for (int i = 0; i < size; i++) {
+                if (Bytes.equals(columnKeys.get(i), columnKey)) {
+                    stopIndex = i;
+                    break;
+                }
+            }
+            if (stopIndex == size) {
+                /*
+                 * The column key is not present in the list. So add it at the specified index
+                 * and right shift the elements at this index and beyond.
+                 */
+                columnKeys.add(index, columnKey);
+            } else {
+                /*
+                 * The column key is already present in the list.
+                 * Move the elements of the list to the left up to the stop index
+                 */
+                for (int i = stopIndex; i > index; i--) {
+                    columnKeys.set(i, columnKeys.get(i - 1));
+                }
+                columnKeys.set(index, columnKey);
+            }
+        }
+        
+        private int getOrdinalPositionFromListIdx(int listIndex) {
+            checkArgument(listIndex < columnKeys.size());
+            return listIndex + offset;
+        }
+        
+        /**
+         * @param columnKey
+         * @return if present - the ordinal position of the column in this list.
+         * If not present - -1.
+         */
+        private int getOrdinalPositionOfColumn(byte[] columnKey) {
+            int i = 0;
+            for (byte[] key : columnKeys) {
+                if (Bytes.equals(key, columnKey)) {
+                    return i + offset;
+                }
+                i++;
+            }
+            return -1;
+        }
+    }
+    
+    private static byte[] getColumnKey(byte[] viewKey, PColumn column) {
+        return getColumnKey(viewKey, column.getName().getString(), column.getFamilyName() != null ? column.getFamilyName().getString() : null);
+    }
+    
+    private static byte[] getColumnKey(byte[] viewKey, String columnName, String columnFamily) {
+        byte[] columnKey = ByteUtil.concat(viewKey, QueryConstants.SEPARATOR_BYTE_ARRAY,
+                Bytes.toBytes(columnName));
+        if (columnFamily != null) {
+            columnKey = ByteUtil.concat(columnKey, QueryConstants.SEPARATOR_BYTE_ARRAY,
+                    Bytes.toBytes(columnFamily));
+        }
+        return columnKey;
+    }
+    
+    MetaDataMutationResult addRowsToChildViews(PTable basePhysicalTable, List<Mutation> tableMetadata, List<Mutation> mutationsForAddingColumnsToViews, byte[] schemaName, byte[] tableName,
             List<ImmutableBytesPtr> invalidateList, long clientTimeStamp, TableViewFinderResult childViewsResult,
             Region region, List<RowLock> locks) throws IOException, SQLException {
+        List<PutWithOrdinalPosition> columnPutsForBaseTable = new ArrayList<>(tableMetadata.size());
+        // Isolate the puts relevant to adding columns. Also figure out what kind of columns are being added.
+        for (Mutation m : tableMetadata) {
+            if (m instanceof Put) {
+                byte[][] rkmd = new byte[5][];
+                int pkCount = getVarChars(m.getRow(), rkmd);
+                if (m instanceof Put && pkCount > COLUMN_NAME_INDEX
+                        && Bytes.compareTo(schemaName, rkmd[SCHEMA_NAME_INDEX]) == 0
+                        && Bytes.compareTo(tableName, rkmd[TABLE_NAME_INDEX]) == 0) {
+                    columnPutsForBaseTable.add(new PutWithOrdinalPosition((Put)m, getInteger((Put)m, TABLE_FAMILY_BYTES, ORDINAL_POSITION_BYTES)));
+                }
+            }
+        }
+        // Sort the puts by ordinal position 
+        Collections.sort(columnPutsForBaseTable);
+        assert columnPutsForBaseTable.size() > 0;
         for (Result viewResult : childViewsResult.getResults()) {
+            short deltaNumPkColsSoFar = 0;
+            short columnsAddedToView = 0;
+            short columnsAddedToBaseTable = 0;
             byte[][] rowViewKeyMetaData = new byte[3][];
             getVarChars(viewResult.getRow(), 3, rowViewKeyMetaData);
-            byte[] viewTenantId = rowViewKeyMetaData[PhoenixDatabaseMetaData.TENANT_ID_INDEX];
-            byte[] viewSchemaName = rowViewKeyMetaData[PhoenixDatabaseMetaData.SCHEMA_NAME_INDEX];
-            byte[] viewName = rowViewKeyMetaData[PhoenixDatabaseMetaData.TABLE_NAME_INDEX];
-            byte[] viewKey = SchemaUtil.getTableKey(viewTenantId, viewSchemaName, viewName);
+            byte[] viewKey = SchemaUtil.getTableKey(rowViewKeyMetaData[PhoenixDatabaseMetaData.TENANT_ID_INDEX],
+                    rowViewKeyMetaData[PhoenixDatabaseMetaData.SCHEMA_NAME_INDEX],
+                    rowViewKeyMetaData[PhoenixDatabaseMetaData.TABLE_NAME_INDEX]);
+            
             // lock the rows corresponding to views so that no other thread can modify the view meta-data
             RowLock viewRowLock = acquireLock(region, viewKey, locks);
             PTable view = doGetTable(viewKey, clientTimeStamp, viewRowLock);
-            if (view.getBaseColumnCount() == QueryConstants.DIVERGED_VIEW_BASE_COLUMN_COUNT) {
-                // if a view has diverged from the base table, we don't allow schema changes
-                // to be propagated to it.
-                // FIXME: We should allow PK changes to be propagated to a diverged view See PHOENIX-2110
-                continue;
-            }
-            int numColsAddedToBaseTable = 0;
-            int numColsAddedToView = 0;
-            short deltaNumPkColsSoFar = 0;
-            PColumn existingViewColumn = null;
-            List<PColumn> viewPkColumns = Lists.newArrayList(view.getPKColumns());
-            boolean addingPKColumn=false;
-            for (Mutation m : tableMetadata) {
+            
+            ColumnOrdinalPositionUpdateList ordinalPositionList = new ColumnOrdinalPositionUpdateList();
+            List<PColumn> viewPkCols = new ArrayList<>(view.getPKColumns());
+            boolean addingExistingPkCol = false;
+            int numCols = view.getColumns().size();
+            for (PutWithOrdinalPosition p : columnPutsForBaseTable) {
+                Put baseTableColumnPut = p.put;
+                PColumn existingViewColumn = null;
                 byte[][] rkmd = new byte[5][];
-                int pkCount = getVarChars(m.getRow(), rkmd);
-                if (m instanceof Put && pkCount > COLUMN_NAME_INDEX
-                        && Bytes.compareTo(schemaName, rkmd[SCHEMA_NAME_INDEX]) == 0
-                        && Bytes.compareTo(tableName, rkmd[TABLE_NAME_INDEX]) == 0) {
-                	try {
-                        // Maybe deserving of a new SchemaUtil.getColumnByName(byte[] familyName, String columnName) function 
-                        String columnName = Bytes.toString(rkmd[COLUMN_NAME_INDEX]);
-                        existingViewColumn = rkmd[FAMILY_NAME_INDEX] == null 
-                            ? view.getPKColumn(columnName) 
-                            : view.getColumnFamily(rkmd[FAMILY_NAME_INDEX]).getColumn(columnName);
-                    } 
-                	catch (ColumnFamilyNotFoundException e) {
+                getVarChars(baseTableColumnPut.getRow(), rkmd);
+                String columnName = Bytes.toString(rkmd[COLUMN_NAME_INDEX]);
+                String columnFamily = rkmd[FAMILY_NAME_INDEX] == null ? null : Bytes.toString(rkmd[FAMILY_NAME_INDEX]);
+                try {
+                    existingViewColumn = columnFamily == null ? view.getColumn(columnName) : view.getColumnFamily(
+                            columnFamily).getColumn(columnName);
+                } catch (ColumnFamilyNotFoundException e) {
+                    // ignore since it means that the column family is not present for the column to be added.
+                } catch (ColumnNotFoundException e) {
+                    // ignore since it means the column is not present in the view
+                }
+                
+                boolean isPkCol = columnFamily == null;
+                byte[] columnKey = getColumnKey(viewKey, columnName, columnFamily);
+                if (existingViewColumn != null) {
+                    MetaDataMutationResult result = validateColumnForAddToBaseTable(existingViewColumn, baseTableColumnPut, basePhysicalTable, isPkCol, view);
+                    if (result != null) {
+                        return result;
                     }
-                	catch (ColumnNotFoundException e) {
-                    } // Ignore - means column family or column name don't exist
-                	
-                    Put p = (Put)m;
-                    byte[] columnKey = ByteUtil.concat(viewKey, QueryConstants.SEPARATOR_BYTE_ARRAY, rkmd[COLUMN_NAME_INDEX]);
-                    if (rkmd[FAMILY_NAME_INDEX] != null) {
-                        columnKey = ByteUtil.concat(columnKey, QueryConstants.SEPARATOR_BYTE_ARRAY, rkmd[FAMILY_NAME_INDEX]);
+                    if (isPkCol) {
+                        viewPkCols.remove(existingViewColumn);
+                        addingExistingPkCol = true;
                     }
-                    Put viewColumnDefinitionPut = new Put(columnKey, clientTimeStamp);
-                    for (Cell cell : p.getFamilyCellMap().values().iterator().next()) {
-                        viewColumnDefinitionPut.add(CellUtil.createCell(columnKey, CellUtil.cloneFamily(cell),
+                    /*
+                     * For views that are not diverged, we need to make sure that the existing columns
+                     * have the same ordinal position as in the base table. This is important because
+                     * we rely on the ordinal position of the column to figure out whether dropping a 
+                     * column from the view will end up diverging the view from the base table.
+                     * 
+                     * For already diverged views, we don't care about the ordinal position of the existing column.
+                     */
+                    if (!isDivergedView(view)) {
+                        int newOrdinalPosition = p.ordinalPosition;
+                        // Check if the ordinal position of the column was getting updated from previous add column
+                        // mutations.
+                        int existingOrdinalPos = ordinalPositionList.getOrdinalPositionOfColumn(columnKey);
+                        if (ordinalPositionList.size() == 0) {
+                            /*
+                             * No ordinal positions to be updated are in the list. In that case, check whether the
+                             * existing ordinal position of the column is different from its new ordinal position.
+                             * If yes, then initialize the ordinal position list with this column's ordinal position
+                             * as the offset.
+                             */
+                            existingOrdinalPos = getOrdinalPosition(view, existingViewColumn);
+                            if (existingOrdinalPos != newOrdinalPosition) {
+                                ordinalPositionList.setOffset(newOrdinalPosition);
+                                ordinalPositionList.addColumn(columnKey, newOrdinalPosition);
+                                for (PColumn col : view.getColumns()) {
+                                    int ordinalPos = getOrdinalPosition(view, col);
+                                    if (ordinalPos >= newOrdinalPosition) {
+                                        if (ordinalPos == existingOrdinalPos) {
+                                            /*
+                                             * No need to update ordinal positions of columns beyond the existing column's 
+                                             * old ordinal position.
+                                             */
+                                            break;
+                                        }
+                                        // increment ordinal position of columns occurring after this column by 1
+                                        int updatedPos = ordinalPos + 1;
+                                        ordinalPositionList.addColumn(getColumnKey(viewKey, col), updatedPos);
+                                    } 
+                                }
+                            } 
+                        } else {
+                            if (existingOrdinalPos != newOrdinalPosition) {
+                                ordinalPositionList.addColumn(columnKey, newOrdinalPosition);
+                            }
+                        }
+                        columnsAddedToBaseTable++;
+                    }
+                } else {
+                    // The column doesn't exist in the view.
+                    Put viewColumnPut = new Put(columnKey, clientTimeStamp);
+                    for (Cell cell : baseTableColumnPut.getFamilyCellMap().values().iterator().next()) {
+                        viewColumnPut.add(CellUtil.createCell(columnKey, CellUtil.cloneFamily(cell),
                                 CellUtil.cloneQualifier(cell), cell.getTimestamp(), cell.getTypeByte(),
                                 CellUtil.cloneValue(cell)));
                     }
-                    
-                    // if there is already a view column with the same name as the base table column we are trying to add
-                	if (existingViewColumn != null) {
-                		List<Cell> dataTypes = viewColumnDefinitionPut
-                                .get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                        PhoenixDatabaseMetaData.DATA_TYPE_BYTES);
-                		if (dataTypes != null && dataTypes.size() > 0) {
-                            Cell cell = dataTypes.get(0);
-                            int typeId = PInteger.INSTANCE.getCodec().decodeInt(cell.getValueArray(), cell.getValueOffset(), SortOrder.getDefault());
-                    		PDataType dataType = PDataType.fromTypeId(typeId);
-                    		if (!existingViewColumn.getDataType().equals(dataType)) {
-                    			 return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
-                    		}
-                		}
-                		// if adding a pk column to the base table
-                		if (rkmd[FAMILY_NAME_INDEX] == null && rkmd[COLUMN_NAME_INDEX] != null) {
-	                        List<Cell> keySeqCells = viewColumnDefinitionPut.get(
-	                                PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-	                                PhoenixDatabaseMetaData.KEY_SEQ_BYTES);
-	                        if (keySeqCells != null && keySeqCells.size() > 0) {
-	                        	Cell cell = keySeqCells.get(0);
-	                        	int keySeq = PSmallint.INSTANCE.getCodec().decodeInt(cell.getValueArray(), cell.getValueOffset(), SortOrder.getDefault());
-	                     		int pkPosition = SchemaUtil.getPKPosition(view, existingViewColumn)+1;
-	                     		if (pkPosition!=keySeq) {
-	                     			return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
-	                     		}
-	                        }
-	                        List<Cell> sortOrders = viewColumnDefinitionPut.get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                    PhoenixDatabaseMetaData.SORT_ORDER_BYTES);
-	                        SortOrder sortOrder = SortOrder.getDefault();
-                            if (sortOrders != null && sortOrders.size() > 0) {
-                            	Cell cell = sortOrders.get(0);
-                            	int sortOrderInt = PInteger.INSTANCE.getCodec().decodeInt(cell.getValueArray(), cell.getValueOffset(), SortOrder.getDefault());
-                            	sortOrder = SortOrder.fromSystemValue(sortOrderInt);                            	
-                            }
-                            if (!Objects.equal(sortOrder,existingViewColumn.getSortOrder())) {
-                        		return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
-                        	}
-	                        viewPkColumns.remove(existingViewColumn);
-                        }
-                		// if there is an existing view column that matches the column being added to the base table and if the column being added has a null
-                    	// scale or maxLength, we need to explicitly do a put to set the scale or maxLength to null (in case the view column has the scale or 
-                    	// max length set)
-                		Integer maxLength = null;
-                		List<Cell> columnSizes = viewColumnDefinitionPut.get(
-                                PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                PhoenixDatabaseMetaData.COLUMN_SIZE_BYTES);
-                        if (columnSizes != null && columnSizes.size() > 0) {
-                            Cell cell = columnSizes.get(0);
-                            maxLength = cell.getValueArray()==null ? null :
-                    		PInteger.INSTANCE.getCodec().decodeInt(cell.getValueArray(), cell.getValueOffset(), SortOrder.getDefault());
-                        }
-                        if (!Objects.equal(maxLength,existingViewColumn.getMaxLength())) {
-                        	return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null); 
-                        }
-                        Integer scale = null;
-                        List<Cell> decimalDigits = viewColumnDefinitionPut.get(
-                                PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                PhoenixDatabaseMetaData.DECIMAL_DIGITS_BYTES);
-                        if (decimalDigits != null && decimalDigits.size() > 0) {
-                            Cell cell = decimalDigits.get(0);
-                            scale = cell.getValueArray()==null ? null :
-                        	PInteger.INSTANCE.getCodec().decodeInt(cell.getValueArray(), cell.getValueOffset(), SortOrder.getDefault());
-                        }
-                        if (!Objects.equal(scale,existingViewColumn.getScale())) {	
-                        	return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null); 
+                    if (isDivergedView(view)) {
+                        if (isPkCol) {
+                            /* 
+                             * Only pk cols of the base table are added to the diverged views. These pk 
+                             * cols are added at the end.
+                             */
+                            int lastOrdinalPos = getOrdinalPosition(view, view.getColumns().get(numCols - 1));
+                            int newPosition = ++lastOrdinalPos;
+                            byte[] ptr = new byte[PInteger.INSTANCE.getByteSize()];
+                            PInteger.INSTANCE.getCodec().encodeInt(newPosition, ptr, 0);
+                            viewColumnPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                                    PhoenixDatabaseMetaData.ORDINAL_POSITION_BYTES, clientTimeStamp, ptr);
+                            mutationsForAddingColumnsToViews.add(viewColumnPut);
+                        } else {
+                            continue; // move on to the next column
                         }
-                	}
-                	else {
-                    	// if we are adding a column that already exists in the view, no need to update the base table or view table column count
-                    	numColsAddedToView++;
-                    } 
-                    	
-                	
-                    numColsAddedToBaseTable++;
-                    mutationsForAddingColumnsToViews.add(viewColumnDefinitionPut);
-                    if (rkmd[FAMILY_NAME_INDEX] == null && rkmd[COLUMN_NAME_INDEX] != null) {
+                    } else {
+                        int newOrdinalPosition = p.ordinalPosition;
                         /*
-                         * If adding a pk column to the base table (and hence the view), see if there are any indexes on
-                         * the view. If yes, then generate puts for the index header row and column rows.
+                         * For a non-diverged view, we need to make sure that the base table column
+                         * is added at the right position.
                          */
-                    	addingPKColumn=true;
-                        deltaNumPkColsSoFar++;
-                        for (PTable index : view.getIndexes()) {
-                            int oldNumberOfColsInIndex = index.getColumns().size();
-                            
-                            byte[] indexColumnKey = ByteUtil.concat(getViewIndexHeaderRowKey(index),
-                                    QueryConstants.SEPARATOR_BYTE_ARRAY,
-                                    IndexUtil.getIndexColumnName(rkmd[FAMILY_NAME_INDEX], rkmd[COLUMN_NAME_INDEX]));
-                            Put indexColumnDefinitionPut = new Put(indexColumnKey, clientTimeStamp);
-                            
-                            // Set the index specific data type for the column
-                            List<Cell> dataTypes = viewColumnDefinitionPut
-                                    .get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                            PhoenixDatabaseMetaData.DATA_TYPE_BYTES);
-                            if (dataTypes != null && dataTypes.size() > 0) {
-                                Cell dataType = dataTypes.get(0);
-                                int dataColumnDataType = PInteger.INSTANCE.getCodec().decodeInt(
-                                        dataType.getValueArray(), dataType.getValueOffset(), SortOrder.ASC);
-                                int indexColumnDataType = IndexUtil.getIndexColumnDataType(true,
-                                        PDataType.fromTypeId(dataColumnDataType)).getSqlType();
-                                byte[] indexColumnDataTypeBytes = new byte[PInteger.INSTANCE.getByteSize()];
-                                PInteger.INSTANCE.getCodec().encodeInt(indexColumnDataType, indexColumnDataTypeBytes, 0);
-                                indexColumnDefinitionPut.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                        PhoenixDatabaseMetaData.DATA_TYPE_BYTES, indexColumnDataTypeBytes);
-                            }
-                            
-                            // Set precision
-                            List<Cell> decimalDigits = viewColumnDefinitionPut.get(
-                                    PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                    PhoenixDatabaseMetaData.DECIMAL_DIGITS_BYTES);
-                            if (decimalDigits != null && decimalDigits.size() > 0) {
-                                Cell decimalDigit = decimalDigits.get(0);
-                                indexColumnDefinitionPut.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                        PhoenixDatabaseMetaData.DECIMAL_DIGITS_BYTES, decimalDigit.getValueArray());
+                        if (ordinalPositionList.size() == 0) {
+                            ordinalPositionList.setOffset(newOrdinalPosition);
+                            ordinalPositionList.addColumn(columnKey, newOrdinalPosition);
+                            for (PColumn col : view.getColumns()) {
+                                int ordinalPos = getOrdinalPosition(view, col);
+                                if (ordinalPos >= newOrdinalPosition) {
+                                    // increment ordinal position of columns by 1
+                                    int updatedPos = ordinalPos + 1;
+                                    ordinalPositionList.addColumn(getColumnKey(viewKey, col), updatedPos);
+                                } 
                             }
-                            
-                            // Set size
-                            List<Cell> columnSizes = viewColumnDefinitionPut.get(
-                                    PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                    PhoenixDatabaseMetaData.COLUMN_SIZE_BYTES);
-                            if (columnSizes != null && columnSizes.size() > 0) {
-                                Cell columnSize = columnSizes.get(0);
-                                indexColumnDefinitionPut.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                        PhoenixDatabaseMetaData.COLUMN_SIZE_BYTES, columnSize.getValueArray());
-                            }
-                            
-                            // Set sort order
-                            List<Cell> sortOrders = viewColumnDefinitionPut.get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                    PhoenixDatabaseMetaData.SORT_ORDER_BYTES);
-                            if (sortOrders != null && sortOrders.size() > 0) {
-                                Cell sortOrder = sortOrders.get(0);
-                                indexColumnDefinitionPut.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                        PhoenixDatabaseMetaData.SORT_ORDER_BYTES, sortOrder.getValueArray());
-                            }
-                            
-                            // Set data table name
-                            List<Cell> dataTableNames = viewColumnDefinitionPut.get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                    PhoenixDatabaseMetaData.DATA_TABLE_NAME_BYTES);
-                            if (dataTableNames != null && dataTableNames.size() > 0) {
-                                Cell dataTableName = dataTableNames.get(0);
-                                indexColumnDefinitionPut.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                        PhoenixDatabaseMetaData.DATA_TABLE_NAME_BYTES, dataTableName.getValueArray());
-                            }
-                            
-                            // Set the ordinal position of the new column.
-                            byte[] ordinalPositionBytes = new byte[PInteger.INSTANCE.getByteSize()];
-                            int ordinalPositionOfNewCol = oldNumberOfColsInIndex + deltaNumPkColsSoFar;
-                            PInteger.INSTANCE.getCodec().encodeInt(ordinalPositionOfNewCol, ordinalPositionBytes, 0);
-                            indexColumnDefinitionPut.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                        PhoenixDatabaseMetaData.ORDINAL_POSITION_BYTES, ordinalPositionBytes);
-                            
-                            // New PK columns have to be nullable after the first DDL
-                            byte[] isNullableBytes = PBoolean.INSTANCE.toBytes(true);
-                            indexColumnDefinitionPut.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                        PhoenixDatabaseMetaData.NULLABLE_BYTES, isNullableBytes);
-                            
-                            // Set the key sequence for the pk column to be added
-                            short currentKeySeq = SchemaUtil.getMaxKeySeq(index);
-                            short newKeySeq = (short)(currentKeySeq + deltaNumPkColsSoFar);
-                            byte[] keySeqBytes = new byte[PSmallint.INSTANCE.getByteSize()];
-                            PSmallint.INSTANCE.getCodec().encodeShort(newKeySeq, keySeqBytes, 0);
-                            indexColumnDefinitionPut.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                                    PhoenixDatabaseMetaData.KEY_SEQ_BYTES, keySeqBytes);
-                            
-                            mutationsForAddingColumnsToViews.add(indexColumnDefinitionPut);
+                        } else {
+                            ordinalPositionList.addColumn(columnKey, newOrdinalPosition);
                         }
+                        mutationsForAddingColumnsToViews.add(viewColumnPut);
                     }
+                    if (isPkCol) {
+                        deltaNumPkColsSoFar++;
+                        // Set the key sequence for the pk column to be added
+                        short currentKeySeq = SchemaUtil.getMaxKeySeq(view);
+                        short newKeySeq = (short)(currentKeySeq + deltaNumPkColsSoFar);
+                        byte[] keySeqBytes = new byte[PSmallint.INSTANCE.getByteSize()];
+                        PSmallint.INSTANCE.getCodec().encodeShort(newKeySeq, keySeqBytes, 0);
+                        viewColumnPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                                PhoenixDatabaseMetaData.KEY_SEQ_BYTES, keySeqBytes);
+                        addMutationsForAddingPkColsToViewIndexes(mutationsForAddingColumnsToViews, clientTimeStamp, view,
+                                deltaNumPkColsSoFar, columnName, viewColumnPut);
+                    }
+                    columnsAddedToView++;
+                    columnsAddedToBaseTable++;
                 }
             }
-            // allow adding a pk columns to base table :
-            // 1. if all the view pk columns are exactly the same as the base table pk columns
-            // 2. if we are adding all the existing view pk columns to the base table 
-            if (addingPKColumn && !viewPkColumns.equals(table.getPKColumns())) {
-            	return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
+            /*
+             * Allow adding a pk columns to base table : 1. if all the view pk columns are exactly the same as the base
+             * table pk columns 2. if we are adding all the existing view pk columns to the base table
+             */ 
+            if (addingExistingPkCol && !viewPkCols.equals(basePhysicalTable.getPKColumns())) {
+                return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), basePhysicalTable);
             }
-            if (deltaNumPkColsSoFar > 0) {
-                for (PTable index : view.getIndexes()) {
-                    byte[] indexHeaderRowKey = getViewIndexHeaderRowKey(index);
-                    Put indexHeaderRowMutation = new Put(indexHeaderRowKey);
-                    
-                    // increment sequence number
-                    long newSequenceNumber = index.getSequenceNumber() + 1;
-                    byte[] newSequenceNumberPtr = new byte[PLong.INSTANCE.getByteSize()];
-                    PLong.INSTANCE.getCodec().encodeLong(newSequenceNumber, newSequenceNumberPtr, 0);
-                    indexHeaderRowMutation.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                            PhoenixDatabaseMetaData.TABLE_SEQ_NUM_BYTES, newSequenceNumberPtr);
-                    
-                    // increase the column count
-                    int newColumnCount = index.getColumns().size() + deltaNumPkColsSoFar;
-                    byte[] newColumnCountPtr = new byte[PInteger.INSTANCE.getByteSize()];
-                    PInteger.INSTANCE.getCodec().encodeInt(newColumnCount, newColumnCountPtr, 0);
-                    indexHeaderRowMutation.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                            PhoenixDatabaseMetaData.COLUMN_COUNT_BYTES, newColumnCountPtr);
-                    
-                    // add index row header key to the invalidate list to force clients to fetch the latest meta-data
-                    invalidateList.add(new ImmutableBytesPtr(indexHeaderRowKey));
-                    if (index.rowKeyOrderOptimizable()) {
-                        UpgradeUtil.addRowKeyOrderOptimizableCell(mutationsForAddingColumnsToViews, indexHeaderRowKey, clientTimeStamp);
-                    }
-                    mutationsForAddingColumnsToViews.add(indexHeaderRowMutation);
+            addViewIndexesHeaderRowMutations(mutationsForAddingColumnsToViews, invalidateList, clientTimeStamp, view,
+                    deltaNumPkColsSoFar);
+            
+            // Update the view header rows with new column counts.
+            Put viewHeaderRowPut = new Put(viewKey, clientTimeStamp);
+            if (!isDivergedView(view) && columnsAddedToBaseTable > 0) {
+                // Base column count should only be updated for diverged views.
+                int oldBaseColumnCount = view.getBaseColumnCount();
+                byte[] baseColumnCountPtr = new byte[PInteger.INSTANCE.getByteSize()];
+                PInteger.INSTANCE.getCodec().encodeInt(oldBaseColumnCount + columnsAddedToBaseTable, baseColumnCountPtr, 0);
+                viewHeaderRowPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                        PhoenixDatabaseMetaData.BASE_COLUMN_COUNT_BYTES, clientTimeStamp, baseColumnCountPtr);
+            }
+            
+            if (columnsAddedToView > 0) {
+                byte[] columnCountPtr = new byte[PInteger.INSTANCE.getByteSize()];
+                PInteger.INSTANCE.getCodec().encodeInt(numCols + columnsAddedToView, columnCountPtr, 0);
+                viewHeaderRowPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                        PhoenixDatabaseMetaData.COLUMN_COUNT_BYTES, clientTimeStamp, columnCountPtr);
+            }
+            
+            /*
+             * Increment the sequence number by 1 if:
+             * 1) For a diverged view, there were columns (pk columns) added to the view.
+             * 2) For a non-diverged view if the base column count changed.
+             *    
+             */
+            boolean changeSequenceNumber = (isDivergedView(view) && columnsAddedToView > 0)
+                    || (!isDivergedView(view) && columnsAddedToBaseTable > 0);
+            if (changeSequenceNumber) {
+                byte[] viewSequencePtr = new byte[PLong.INSTANCE.getByteSize()];
+                PLong.INSTANCE.getCodec().encodeLong(view.getSequenceNumber() + 1, viewSequencePtr, 0);
+                viewHeaderRowPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                        PhoenixDatabaseMetaData.TABLE_SEQ_NUM_BYTES, clientTimeStamp, viewSequencePtr);
+
+                mutationsForAddingColumnsToViews.add(viewHeaderRowPut);
+
+                // only invalidate if the sequence number is about to change
+                invalidateList.add(new ImmutableBytesPtr(viewKey));
+
+                // Update the ordinal positions. The list would be non-empty only if the sequence
+                // number will change.
+                int i = 0;
+                for (byte[] columnKey : ordinalPositionList.columnKeys) {
+                    int ordinalPosition = ordinalPositionList.getOrdinalPositionFromListIdx(i);
+                    Put positionUpdatePut = new Put(columnKey, clientTimeStamp);
+                    byte[] ptr = new byte[PInteger.INSTANCE.getByteSize()];
+                    PInteger.INSTANCE.getCodec().encodeInt(ordinalPosition, ptr, 0);
+                    positionUpdatePut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                            PhoenixDatabaseMetaData.ORDINAL_POSITION_BYTES, clientTimeStamp, ptr);
+                    mutationsForAddingColumnsToViews.add(positionUpdatePut);
+                    i++;
                 }
             }
-
-            int oldBaseColumnCount = view.getBaseColumnCount();
-
-            Put viewHeaderRowPut = new Put(viewKey, clientTimeStamp);
-            byte[] baseColumnCountPtr = new byte[PInteger.INSTANCE.getByteSize()];
-            PInteger.INSTANCE.getCodec().encodeInt(oldBaseColumnCount + numColsAddedToBaseTable, baseColumnCountPtr, 0);
-            byte[] columnCountPtr = new byte[PInteger.INSTANCE.getByteSize()];
-            PInteger.INSTANCE.getCodec().encodeInt(view.getColumns().size() + numColsAddedToView, columnCountPtr, 0);
-            byte[] viewSequencePtr = new byte[PLong.INSTANCE.getByteSize()];
-            PLong.INSTANCE.getCodec().encodeLong(view.getSequenceNumber() + 1, viewSequencePtr, 0);
-            viewHeaderRowPut.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                    PhoenixDatabaseMetaData.COLUMN_COUNT_BYTES, clientTimeStamp, columnCountPtr);
-            viewHeaderRowPut.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                    PhoenixDatabaseMetaData.BASE_COLUMN_COUNT_BYTES, clientTimeStamp, baseColumnCountPtr);
-            viewHeaderRowPut.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                    PhoenixDatabaseMetaData.TABLE_SEQ_NUM_BYTES, clientTimeStamp, viewSequencePtr);
-            mutationsForAddingColumnsToViews.add(viewHeaderRowPut);
+            
             if (view.rowKeyOrderOptimizable()) {
                 UpgradeUtil.addRowKeyOrderOptimizableCell(mutationsForAddingColumnsToViews, viewKey, clientTimeStamp);
             }
+        }
+        return null;
+    }
+    
+    private MetaDataMutationResult validateColumnForAddToBaseTable(PColumn existingViewColumn, Put columnToBeAdded, PTable basePhysicalTable, boolean isColumnToBeAddPkCol, PTable view) {
+        if (existingViewColumn != null) {
+            
+            // Validate data type is same
+            int baseColumnDataType = getInteger(columnToBeAdded, TABLE_FAMILY_BYTES, DATA_TYPE_BYTES);
+            if (baseColumnDataType != existingViewColumn.getDataType().getSqlType()) {
+                return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), basePhysicalTable);
+            }
 
-            // Update positions of view columns
-            for (PColumn column : view.getColumns()) {
-                if (column.getPosition() >= oldBaseColumnCount) {
-                    int newPosition = column.getPosition() + numColsAddedToView + 1;
-
-                    byte[] k = ByteUtil.concat(viewKey, QueryConstants.SEPARATOR_BYTE_ARRAY, column.getName()
-                            .getBytes());
-                    if (column.getFamilyName() != null) {
-                        k = ByteUtil.concat(k, QueryConstants.SEPARATOR_BYTE_ARRAY, column.getFamilyName().getBytes());
-                    }
-
-                    Put positionUpdatePut = new Put(k, clientTimeStamp);
-                    byte[] ptr = new byte[PInteger.INSTANCE.getByteSize()];
-                    PInteger.INSTANCE.getCodec().encodeInt(newPosition, ptr, 0);
-                    positionUpdatePut.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
-                            PhoenixDatabaseMetaData.ORDINAL_POSITION_BYTES, clientTimeStamp, ptr);
-                    mutationsForAddingColumnsToViews.add(positionUpdatePut);
+            // Validate max length is same
+            int maxLength = getInteger(columnToBeAdded, TABLE_FAMILY_BYTES, COLUMN_SIZE_BYTES);
+            int existingMaxLength = existingViewColumn.getMaxLength() == null ? 0 : existingViewColumn.getMaxLength();
+            if (maxLength != existingMaxLength) {
+                return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), basePhysicalTable); 
+            }
+            
+            // Validate scale is same
+            int scale = getInteger(columnToBeAdded, TABLE_FAMILY_BYTES, DECIMAL_DIGITS_BYTES);
+            int existingScale = existingViewColumn.getScale() == null ? 0 : existingViewColumn.getScale();
+            if (scale != existingScale) {
+                return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), basePhysicalTable); 
+            }
+            
+            // Validate sort order is same
+            int sortOrder = getInteger(columnToBeAdded, TABLE_FAMILY_BYTES, SORT_ORDER_BYTES);
+            if (sortOrder != existingViewColumn.getSortOrder().getSystemValue()) {
+                return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), basePhysicalTable);
+            }
+            
+            // if the column to be added to the base table is a pk column, then we need to validate that the key slot position is the same
+            if (isColumnToBeAddPkCol) {
+                List<Cell> keySeqCells = columnToBeAdded.get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                        PhoenixDatabaseMetaData.KEY_SEQ_BYTES);
+                if (keySeqCells != null && keySeqCells.size() > 0) {
+                    Cell cell = keySeqCells.get(0);
+                    int keySeq = PSmallint.INSTANCE.getCodec().decodeInt(cell.getValueArray(), cell.getValueOffset(),
+                            SortOrder.getDefault());
+                    int pkPosition = SchemaUtil.getPKPosition(view, existingViewColumn) + 1;
+                    if (pkPosition != keySeq) { return new MetaDataMutationResult(
+                            MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), basePhysicalTable); }
                 }
             }
-            invalidateList.add(new ImmutableBytesPtr(viewKey));
         }
         return null;
     }
     
+    private int getInteger(Put p, byte[] family, byte[] qualifier) {
+        List<Cell> cells = p.get(family, qualifier);
+        if (cells != null && cells.size() > 0) {
+            Cell cell = cells.get(0);
+            return (Integer)PInteger.INSTANCE.toObject(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
+        }
+        return 0;
+    }
+    
+    private void addViewIndexesHeaderRowMutations(List<Mutation> mutationsForAddingColumnsToViews,
+            List<ImmutableBytesPtr> invalidateList, long clientTimeStamp, PTable view, short deltaNumPkColsSoFar) {
+        if (deltaNumPkColsSoFar > 0) {
+            for (PTable index : view.getIndexes()) {
+                byte[] indexHeaderRowKey = getViewIndexHeaderRowKey(index);
+                Put indexHeaderRowMutation = new Put(indexHeaderRowKey);
+                
+                // increment sequence number
+                long newSequenceNumber = index.getSequenceNumber() + 1;
+                byte[] newSequenceNumberPtr = new byte[PLong.INSTANCE.getByteSize()];
+                PLong.INSTANCE.getCodec().encodeLong(newSequenceNumber, newSequenceNumberPtr, 0);
+                indexHeaderRowMutation.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                        PhoenixDatabaseMetaData.TABLE_SEQ_NUM_BYTES, newSequenceNumberPtr);
+                
+                // increase the column count
+                int newColumnCount = index.getColumns().size() + deltaNumPkColsSoFar;
+                byte[] newColumnCountPtr = new byte[PInteger.INSTANCE.getByteSize()];
+                PInteger.INSTANCE.getCodec().encodeInt(newColumnCount, newColumnCountPtr, 0);
+                indexHeaderRowMutation.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                        PhoenixDatabaseMetaData.COLUMN_COUNT_BYTES, newColumnCountPtr);
+                
+                // add index row header key to the invalidate list to force clients to fetch the latest meta-data
+                invalidateList.add(new ImmutableBytesPtr(indexHeaderRowKey));
+                if (index.rowKeyOrderOptimizable()) {
+                    UpgradeUtil.addRowKeyOrderOptimizableCell(mutationsForAddingColumnsToViews, indexHeaderRowKey, clientTimeStamp);
+                }
+                mutationsForAddingColumnsToViews.add(indexHeaderRowMutation);
+            }
+        }
+    }
+
+    private void addMutationsForAddingPkColsToViewIndexes(List<Mutation> mutationsForAddingColumnsToViews, long clientTimeStamp,
+            PTable view, short deltaNumPkColsSoFar, String viewPkColumnName, Put viewColumnDefinitionPut) {
+        for (PTable index : view.getIndexes()) {
+            int oldNumberOfColsInIndex = index.getColumns().size();
+            
+            byte[] indexColumnKey = ByteUtil.concat(getViewIndexHeaderRowKey(index), QueryConstants.SEPARATOR_BYTE_ARRAY, Bytes.toBytes(IndexUtil.getIndexColumnName(null, viewPkColumnName)));
+            Put indexColumnDefinitionPut = new Put(indexColumnKey, clientTimeStamp);
+            
+            // Set the index specific data type for the column
+            int viewPkColumnDataType = getInteger(viewColumnDefinitionPut, TABLE_FAMILY_BYTES, DATA_TYPE_BYTES);
+            byte[] indexColumnDataTypeBytes = new byte[PInteger.INSTANCE.getByteSize()];
+            int indexColumnDataType = IndexUtil.getIndexColumnDataType(true,
+                    PDataType.fromTypeId(viewPkColumnDataType)).getSqlType();
+            PInteger.INSTANCE.getCodec().encodeInt(indexColumnDataType, indexColumnDataTypeBytes, 0);
+            indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                    PhoenixDatabaseMetaData.DATA_TYPE_BYTES, indexColumnDataTypeBytes);
+            
+             
+            // Set precision
+            List<Cell> decimalDigits = viewColumnDefinitionPut.get(
+                    PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                    PhoenixDatabaseMetaData.DECIMAL_DIGITS_BYTES);
+            if (decimalDigits != null && decimalDigits.size() > 0) {
+                Cell decimalDigit = decimalDigits.get(0);
+                indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                        PhoenixDatabaseMetaData.DECIMAL_DIGITS_BYTES, decimalDigit.getValueArray());
+            }
+            
+            // Set size
+            List<Cell> columnSizes = viewColumnDefinitionPut.get(
+                    PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                    PhoenixDatabaseMetaData.COLUMN_SIZE_BYTES);
+            if (columnSizes != null && columnSizes.size() > 0) {
+                Cell columnSize = columnSizes.get(0);
+                indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                        PhoenixDatabaseMetaData.COLUMN_SIZE_BYTES, columnSize.getValueArray());
+            }
+            
+            // Set sort order
+            List<Cell> sortOrders = viewColumnDefinitionPut.get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                    PhoenixDatabaseMetaData.SORT_ORDER_BYTES);
+            if (sortOrders != null && sortOrders.size() > 0) {
+                Cell sortOrder = sortOrders.get(0);
+                indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                        PhoenixDatabaseMetaData.SORT_ORDER_BYTES, sortOrder.getValueArray());
+            }
+            
+            // Set data table name
+            List<Cell> dataTableNames = viewColumnDefinitionPut.get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                    PhoenixDatabaseMetaData.DATA_TABLE_NAME_BYTES);
+            if (dataTableNames != null && dataTableNames.size() > 0) {
+                Cell dataTableName = dataTableNames.get(0);
+                indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                        PhoenixDatabaseMetaData.DATA_TABLE_NAME_BYTES, dataTableName.getValueArray());
+            }
+            
+            // Set the ordinal position of the new column.
+            byte[] ordinalPositionBytes = new byte[PInteger.INSTANCE.getByteSize()];
+            int ordinalPositionOfNewCol = oldNumberOfColsInIndex + deltaNumPkColsSoFar;
+            PInteger.INSTANCE.getCodec().encodeInt(ordinalPositionOfNewCol, ordinalPositionBytes, 0);
+            indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                        PhoenixDatabaseMetaData.ORDINAL_POSITION_BYTES, ordinalPositionBytes);
+            
+            // New PK columns have to be nullable after the first DDL
+            byte[] isNullableBytes = PBoolean.INSTANCE.toBytes(true);
+            indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                        PhoenixDatabaseMetaData.NULLABLE_BYTES, isNullableBytes);
+            
+            // Set the key sequence for the pk column to be added
+            short currentKeySeq = SchemaUtil.getMaxKeySeq(index);
+            short newKeySeq = (short)(currentKeySeq + deltaNumPkColsSoFar);
+            byte[] keySeqBytes = new byte[PSmallint.INSTANCE.getByteSize()];
+            PSmallint.INSTANCE.getCodec().encodeShort(newKeySeq, keySeqBytes, 0);
+            indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+                    PhoenixDatabaseMetaData.KEY_SEQ_BYTES, keySeqBytes);
+            
+            mutationsForAddingColumnsToViews.add(indexColumnDefinitionPut);
+        }
+    }
+    
     private byte[] getViewIndexHeaderRowKey(PTable index) {
         byte[] tenantIdBytes = index.getKey().getTenantId() != null ? index.getKey().getTenantId().getBytes() : EMPTY_BYTE_ARRAY;
         byte[] schemaNameBytes = index.getSchemaName() != null ? index.getSchemaName().getBytes() : EMPTY_BYTE_ARRAY; 


[15/40] phoenix git commit: Prepare for release

Posted by ma...@apache.org.
Prepare for release


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/b7cd7e50
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/b7cd7e50
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/b7cd7e50

Branch: refs/heads/calcite
Commit: b7cd7e505ed14338d9bcd6f49f659e7f067de0d8
Parents: 18fefed
Author: Mujtaba <mu...@apache.org>
Authored: Wed Jul 22 21:49:40 2015 -0700
Committer: Mujtaba <mu...@apache.org>
Committed: Wed Jul 22 21:49:40 2015 -0700

----------------------------------------------------------------------
 dev/make_rc.sh                | 59 ++++++++++++--------------------------
 phoenix-assembly/pom.xml      |  2 +-
 phoenix-core/pom.xml          |  2 +-
 phoenix-flume/pom.xml         |  2 +-
 phoenix-pherf/pom.xml         |  2 +-
 phoenix-pig/pom.xml           |  2 +-
 phoenix-server-client/pom.xml |  2 +-
 phoenix-server/pom.xml        |  2 +-
 phoenix-spark/pom.xml         |  2 +-
 pom.xml                       |  2 +-
 10 files changed, 27 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/b7cd7e50/dev/make_rc.sh
----------------------------------------------------------------------
diff --git a/dev/make_rc.sh b/dev/make_rc.sh
index e23db07..a67c58a 100755
--- a/dev/make_rc.sh
+++ b/dev/make_rc.sh
@@ -36,15 +36,14 @@ DIR_REL_BIN_PATH=$DIR_REL_ROOT/$DIR_REL_BIN
 REL_SRC=phoenix-$PHOENIX-src
 DIR_REL_SRC_TAR_PATH=$DIR_REL_ROOT/src
 DIR_REL_BIN_TAR_PATH=$DIR_REL_ROOT/bin
-DIR_BIN=bin
+DIR_BIN=$DIR_REL_BIN_PATH/bin
 DIR_EXAMPLES=$DIR_REL_BIN_PATH/examples
-DIR_COMMON=$DIR_REL_BIN_PATH/common
-DIR_HADOOP=$DIR_REL_BIN_PATH/hadoop
 DIR_DOCS=dev/release_files
 
 # Verify no target exists
 mvn clean; mvn clean -Dhadoop.profile=2; rm -rf $DIR_REL_BASE;
 RESULT=$(find -iname target)
+
 if [ -z "$RESULT" ]
 then
   echo "Verified target directory does not exist.";
@@ -63,7 +62,7 @@ mkdir $DIR_REL_BIN_PATH;
 mkdir $DIR_REL_BIN_TAR_PATH;
 mkdir $DIR_REL_SRC_TAR_PATH;
 mkdir $DIR_EXAMPLES;
-mkdir $DIR_COMMON;
+mkdir $DIR_BIN;
 
 # Move src tar
 mv $REL_SRC.tar.gz $DIR_REL_SRC_TAR_PATH;
@@ -71,50 +70,28 @@ mv $REL_SRC.tar.gz $DIR_REL_SRC_TAR_PATH;
 # Copy common jars
 mvn clean apache-rat:check package -DskipTests;
 rm -rf $(find . -type d -name archive-tmp);
-cp $(find -iname phoenix-$PHOENIX-client-minimal.jar) $DIR_COMMON;
-cp $(find -iname phoenix-$PHOENIX-client-without-hbase.jar) $DIR_COMMON;
-cp $(find -iname phoenix-core-$PHOENIX.jar) $DIR_COMMON;
-cp $(find -iname phoenix-server-$PHOENIX-runnable.jar) $DIR_COMMON;
-cp $(find -iname phoenix-$PHOENIX-query-server-thin-client.jar) $DIR_COMMON;
 
-# Copy release docs
-function_copy() {
-  if [ ! -f $1 ];
-   then
-    echo ""; echo "ERROR!! Please check-in $1 file before running make_rc.sh"; 
-    exit -1; 
-  fi
-  cp $1 $DIR_REL_BIN_PATH;
-}
+cp $(find -iname phoenix-$PHOENIX-client-minimal.jar) $DIR_REL_BIN_PATH;
+cp $(find -iname phoenix-$PHOENIX-client-without-hbase.jar) $DIR_REL_BIN_PATH;
+cp $(find -iname phoenix-core-$PHOENIX.jar) $DIR_REL_BIN_PATH;
+cp $(find -iname phoenix-$PHOENIX-client.jar) $DIR_REL_BIN_PATH;
+cp $(find -iname phoenix-$PHOENIX-server.jar) $DIR_REL_BIN_PATH;
+cp $(find -iname phoenix-$PHOENIX-server-without-antlr.jar) $DIR_REL_BIN_PATH;
+cp $(find -iname phoenix-core-$PHOENIX-tests.jar) $DIR_REL_BIN_PATH;
+cp $(find -iname phoenix-flume-$PHOENIX.jar) $DIR_REL_BIN_PATH;
+cp $(find -iname phoenix-flume-$PHOENIX-tests.jar) $DIR_REL_BIN_PATH;
+cp $(find -iname phoenix-pig-$PHOENIX.jar) $DIR_REL_BIN_PATH;
+cp $(find -iname phoenix-pig-$PHOENIX-tests.jar) $DIR_REL_BIN_PATH;
+
+# Copy bin
+cp bin/* $DIR_BIN;
 
-function_copy CHANGES;
-function_copy DISCLAIMER;
-function_copy README;
+# Copy release docs
 cp $DIR_DOCS/* $DIR_REL_BIN_PATH;
 
 # Copy examples
 cp -r examples/* $DIR_EXAMPLES
 
-# Copy hadoop specific jars
-function_copy_hadoop_specific_jars() {
-  mkdir $DIR_HADOOP$1;
-  mkdir $DIR_HADOOP$1/$DIR_BIN;
-  cp $DIR_BIN/* $DIR_HADOOP$1/$DIR_BIN;
-  cp $(find -iname phoenix-$PHOENIX-client.jar) $DIR_HADOOP$1/phoenix-$PHOENIX-client-hadoop$1.jar;
-  cp $(find -iname phoenix-$PHOENIX-server.jar) $DIR_HADOOP$1/phoenix-$PHOENIX-server-hadoop$1.jar;
-  cp $(find -iname phoenix-core-$PHOENIX-tests.jar) $DIR_HADOOP$1/phoenix-core-$PHOENIX-tests-hadoop$1.jar;
-  cp $(find -iname phoenix-server-$PHOENIX.jar) $DIR_HADOOP$1/phoenix-server-$PHOENIX-hadoop$1.jar;
-  cp $(find -iname phoenix-server-$PHOENIX-tests.jar) $DIR_HADOOP$1/phoenix-server-$PHOENIX-tests-hadoop$1.jar;
-  cp $(find -iname phoenix-server-client-$PHOENIX.jar) $DIR_HADOOP$1/phoenix-server-client-$PHOENIX-hadoop$1.jar;
-  cp $(find -iname phoenix-flume-$PHOENIX.jar) $DIR_HADOOP$1/phoenix-flume-$PHOENIX-hadoop$1.jar;
-  cp $(find -iname phoenix-flume-$PHOENIX-tests.jar) $DIR_HADOOP$1/phoenix-flume-$PHOENIX-tests-hadoop$1.jar;
-  cp $(find -iname phoenix-pig-$PHOENIX.jar) $DIR_HADOOP$1/phoenix-pig-$PHOENIX-hadoop$1.jar;
-  cp $(find -iname phoenix-pig-$PHOENIX-tests.jar) $DIR_HADOOP$1/phoenix-pig-$PHOENIX-tests-hadoop$1.jar;
-}
-function_copy_hadoop_specific_jars 1;
-mvn clean package -Dhadoop.profile=2 -DskipTests;
-function_copy_hadoop_specific_jars 2;
-
 # Generate bin tar
 tar cvzf $DIR_REL_BIN_TAR_PATH/$DIR_REL_BIN.tar.gz -C $DIR_REL_ROOT phoenix-$PHOENIX-bin;
 rm -rf $DIR_REL_BIN_PATH;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/b7cd7e50/phoenix-assembly/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-assembly/pom.xml b/phoenix-assembly/pom.xml
index 51ff74d..962e08e 100644
--- a/phoenix-assembly/pom.xml
+++ b/phoenix-assembly/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix</artifactId>
-    <version>4.5.0-SNAPSHOT</version>
+    <version>4.5.0-HBase-1.1</version>
   </parent>
   <artifactId>phoenix-assembly</artifactId>
   <name>Phoenix Assembly</name>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/b7cd7e50/phoenix-core/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-core/pom.xml b/phoenix-core/pom.xml
index 9ab2a0e..3288f49 100644
--- a/phoenix-core/pom.xml
+++ b/phoenix-core/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix</artifactId>
-    <version>4.5.0-SNAPSHOT</version>
+    <version>4.5.0-HBase-1.1</version>
   </parent>
   <artifactId>phoenix-core</artifactId>
   <name>Phoenix Core</name>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/b7cd7e50/phoenix-flume/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-flume/pom.xml b/phoenix-flume/pom.xml
index 8b4ee84..0f65f2d 100644
--- a/phoenix-flume/pom.xml
+++ b/phoenix-flume/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix</artifactId>
-    <version>4.5.0-SNAPSHOT</version>
+    <version>4.5.0-HBase-1.1</version>
   </parent>
   <artifactId>phoenix-flume</artifactId>
   <name>Phoenix - Flume</name>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/b7cd7e50/phoenix-pherf/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-pherf/pom.xml b/phoenix-pherf/pom.xml
index 36215db..8343be0 100644
--- a/phoenix-pherf/pom.xml
+++ b/phoenix-pherf/pom.xml
@@ -15,7 +15,7 @@
 	<parent>
 		<groupId>org.apache.phoenix</groupId>
 		<artifactId>phoenix</artifactId>
-		<version>4.5.0-SNAPSHOT</version>
+		<version>4.5.0-HBase-1.1</version>
 	</parent>
 
 	<artifactId>phoenix-pherf</artifactId>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/b7cd7e50/phoenix-pig/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-pig/pom.xml b/phoenix-pig/pom.xml
index 4ad06d1..5370558 100644
--- a/phoenix-pig/pom.xml
+++ b/phoenix-pig/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix</artifactId>
-    <version>4.5.0-SNAPSHOT</version>
+    <version>4.5.0-HBase-1.1</version>
   </parent>
   <artifactId>phoenix-pig</artifactId>
   <name>Phoenix - Pig</name>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/b7cd7e50/phoenix-server-client/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-server-client/pom.xml b/phoenix-server-client/pom.xml
index e23fcba..cea07fd 100644
--- a/phoenix-server-client/pom.xml
+++ b/phoenix-server-client/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix</artifactId>
-    <version>4.5.0-SNAPSHOT</version>
+    <version>4.5.0-HBase-1.1</version>
   </parent>
   <artifactId>phoenix-server-client</artifactId>
   <name>Phoenix Query Server Client</name>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/b7cd7e50/phoenix-server/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-server/pom.xml b/phoenix-server/pom.xml
index 7dd09aa..41cc123 100644
--- a/phoenix-server/pom.xml
+++ b/phoenix-server/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix</artifactId>
-    <version>4.5.0-SNAPSHOT</version>
+    <version>4.5.0-HBase-1.1</version>
   </parent>
   <artifactId>phoenix-server</artifactId>
   <name>Phoenix Query Server</name>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/b7cd7e50/phoenix-spark/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-spark/pom.xml b/phoenix-spark/pom.xml
index ef4d2c4..6269f3d 100644
--- a/phoenix-spark/pom.xml
+++ b/phoenix-spark/pom.xml
@@ -28,7 +28,7 @@
   <parent>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix</artifactId>
-    <version>4.5.0-SNAPSHOT</version>
+    <version>4.5.0-HBase-1.1</version>
   </parent>
   <artifactId>phoenix-spark</artifactId>
   <name>Phoenix - Spark</name>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/b7cd7e50/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 9fa6702..2e2c6c2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.apache.phoenix</groupId>
   <artifactId>phoenix</artifactId>
-  <version>4.5.0-SNAPSHOT</version>
+  <version>4.5.0-HBase-1.1</version>
   <packaging>pom</packaging>
   <name>Apache Phoenix</name>
   <description>A SQL layer over HBase</description>


[38/40] phoenix git commit: PHOENIX-2164 Add LiteralResultIterationQueryPlan for implemention of Values

Posted by ma...@apache.org.
PHOENIX-2164 Add LiteralResultIterationQueryPlan for implemention of Values


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/aa86c899
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/aa86c899
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/aa86c899

Branch: refs/heads/calcite
Commit: aa86c899c9429e84f5b0dd5332c929e8eeb9e311
Parents: 0f84104
Author: maryannxue <we...@intel.com>
Authored: Sat Aug 22 09:22:42 2015 -0400
Committer: maryannxue <we...@intel.com>
Committed: Sat Aug 22 09:22:42 2015 -0400

----------------------------------------------------------------------
 .../apache/phoenix/compile/QueryCompiler.java   |   4 +-
 .../phoenix/execute/EmptyTableQueryPlan.java    |  96 -----------------
 .../execute/LiteralResultIterationPlan.java     | 108 +++++++++++++++++++
 3 files changed, 110 insertions(+), 98 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa86c899/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
index ce3343e..20ba3da 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
@@ -35,10 +35,10 @@ import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
 import org.apache.phoenix.execute.AggregatePlan;
 import org.apache.phoenix.execute.ClientAggregatePlan;
 import org.apache.phoenix.execute.ClientScanPlan;
-import org.apache.phoenix.execute.EmptyTableQueryPlan;
 import org.apache.phoenix.execute.HashJoinPlan;
 import org.apache.phoenix.execute.HashJoinPlan.HashSubPlan;
 import org.apache.phoenix.execute.HashJoinPlan.WhereClauseSubPlan;
+import org.apache.phoenix.execute.LiteralResultIterationPlan;
 import org.apache.phoenix.execute.ScanPlan;
 import org.apache.phoenix.execute.SortMergeJoinPlan;
 import org.apache.phoenix.execute.TupleProjectionPlan;
@@ -557,7 +557,7 @@ public class QueryCompiler {
         if (plan == null) {
             ParallelIteratorFactory parallelIteratorFactory = asSubquery ? null : this.parallelIteratorFactory;
             plan = select.getFrom() == null ?
-                      new EmptyTableQueryPlan(context, select, tableRef, projector, limit, orderBy, parallelIteratorFactory)
+                      new LiteralResultIterationPlan(context, select, tableRef, projector, limit, orderBy, parallelIteratorFactory)
                     : (select.isAggregate() || select.isDistinct() ?
                               new AggregatePlan(context, select, tableRef, projector, limit, orderBy, parallelIteratorFactory, groupBy, having)
                             : new ScanPlan(context, select, tableRef, projector, limit, orderBy, parallelIteratorFactory, allowPageFilter));

http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa86c899/phoenix-core/src/main/java/org/apache/phoenix/execute/EmptyTableQueryPlan.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/EmptyTableQueryPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/EmptyTableQueryPlan.java
deleted file mode 100644
index fd55732..0000000
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/EmptyTableQueryPlan.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.phoenix.execute;
-
-import java.sql.SQLException;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.hadoop.hbase.KeyValue;
-import org.apache.hadoop.hbase.client.Scan;
-import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
-import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
-import org.apache.phoenix.compile.RowProjector;
-import org.apache.phoenix.compile.StatementContext;
-import org.apache.phoenix.iterate.ParallelIteratorFactory;
-import org.apache.phoenix.iterate.ParallelScanGrouper;
-import org.apache.phoenix.iterate.ResultIterator;
-import org.apache.phoenix.iterate.SequenceResultIterator;
-import org.apache.phoenix.parse.FilterableStatement;
-import org.apache.phoenix.query.KeyRange;
-import org.apache.phoenix.schema.TableRef;
-import org.apache.phoenix.schema.tuple.SingleKeyValueTuple;
-import org.apache.phoenix.schema.tuple.Tuple;
-
-public class EmptyTableQueryPlan extends BaseQueryPlan {
-
-    public EmptyTableQueryPlan(StatementContext context, FilterableStatement statement, 
-            TableRef tableRef, RowProjector projection, Integer limit, OrderBy orderBy,
-            ParallelIteratorFactory parallelIteratorFactory) {
-        super(context, statement, tableRef, projection, context.getBindManager().getParameterMetaData(), limit, orderBy, GroupBy.EMPTY_GROUP_BY, parallelIteratorFactory);
-    }
-
-    @Override
-    public List<KeyRange> getSplits() {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public List<List<Scan>> getScans() {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public boolean useRoundRobinIterator() throws SQLException {
-        return false;
-    }
-
-    @Override
-    protected ResultIterator newIterator(ParallelScanGrouper scanGrouper)
-            throws SQLException {
-        ResultIterator scanner = new ResultIterator() {
-            private boolean hasNext = true;
-
-            @Override
-            public void close() throws SQLException {
-                this.hasNext = false;
-            }
-
-            @Override
-            public Tuple next() throws SQLException {
-                if (hasNext) {
-                    hasNext = false;
-                    return new SingleKeyValueTuple(KeyValue.LOWESTKEY);
-                }
-                return null;
-            }
-
-            @Override
-            public void explain(List<String> planSteps) {
-            }
-            
-        };
-        
-        if (context.getSequenceManager().getSequenceCount() > 0) {
-            scanner = new SequenceResultIterator(scanner, context.getSequenceManager());
-        }
-        
-        return scanner;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa86c899/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java
new file mode 100644
index 0000000..e7230cc
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java
@@ -0,0 +1,108 @@
+/*
+ * 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.phoenix.execute;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
+import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
+import org.apache.phoenix.compile.RowProjector;
+import org.apache.phoenix.compile.StatementContext;
+import org.apache.phoenix.iterate.ParallelIteratorFactory;
+import org.apache.phoenix.iterate.ParallelScanGrouper;
+import org.apache.phoenix.iterate.ResultIterator;
+import org.apache.phoenix.iterate.SequenceResultIterator;
+import org.apache.phoenix.parse.FilterableStatement;
+import org.apache.phoenix.query.KeyRange;
+import org.apache.phoenix.schema.TableRef;
+import org.apache.phoenix.schema.tuple.SingleKeyValueTuple;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+public class LiteralResultIterationPlan extends BaseQueryPlan {
+    protected final Iterator<Tuple> tupleIterator;
+
+    public LiteralResultIterationPlan(StatementContext context, 
+            FilterableStatement statement, TableRef tableRef, RowProjector projection, 
+            Integer limit, OrderBy orderBy, ParallelIteratorFactory parallelIteratorFactory) {
+        this(Collections.<Tuple> singletonList(new SingleKeyValueTuple(KeyValue.LOWESTKEY)).iterator(), 
+                context, statement, tableRef, projection, limit, orderBy, parallelIteratorFactory);
+    }
+
+    public LiteralResultIterationPlan(Iterator<Tuple> tupleIterator, StatementContext context, 
+            FilterableStatement statement, TableRef tableRef, RowProjector projection, 
+            Integer limit, OrderBy orderBy, ParallelIteratorFactory parallelIteratorFactory) {
+        super(context, statement, tableRef, projection, context.getBindManager().getParameterMetaData(), limit, orderBy, GroupBy.EMPTY_GROUP_BY, parallelIteratorFactory);
+        this.tupleIterator = tupleIterator;
+    }
+
+    @Override
+    public List<KeyRange> getSplits() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public List<List<Scan>> getScans() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public boolean useRoundRobinIterator() throws SQLException {
+        return false;
+    }
+
+    @Override
+    protected ResultIterator newIterator(ParallelScanGrouper scanGrouper)
+            throws SQLException {
+        ResultIterator scanner = new ResultIterator() {
+            private boolean closed = false;
+            private int count = 0;
+
+            @Override
+            public void close() throws SQLException {
+                this.closed = true;;
+            }
+
+            @Override
+            public Tuple next() throws SQLException {
+                if (!this.closed 
+                        && (limit == null || count++ < limit)
+                        && tupleIterator.hasNext()) {
+                    return tupleIterator.next();
+                }
+                return null;
+            }
+
+            @Override
+            public void explain(List<String> planSteps) {
+            }
+            
+        };
+        
+        if (context.getSequenceManager().getSequenceCount() > 0) {
+            scanner = new SequenceResultIterator(scanner, context.getSequenceManager());
+        }
+        
+        return scanner;
+    }
+
+}


[05/40] phoenix git commit: Simplify Pherf generated dependency jar and pom.xml - Add missing dependency

Posted by ma...@apache.org.
Simplify Pherf generated dependency jar and pom.xml - Add missing dependency


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/d3316ce4
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/d3316ce4
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/d3316ce4

Branch: refs/heads/calcite
Commit: d3316ce4cca01fc0608f381e3d9a5afae68efae7
Parents: 6277fda
Author: Mujtaba <mu...@apache.org>
Authored: Tue Jul 21 17:36:12 2015 -0700
Committer: Mujtaba <mu...@apache.org>
Committed: Tue Jul 21 17:36:12 2015 -0700

----------------------------------------------------------------------
 phoenix-pherf/pom.xml | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/d3316ce4/phoenix-pherf/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-pherf/pom.xml b/phoenix-pherf/pom.xml
index 3817b3a..36215db 100644
--- a/phoenix-pherf/pom.xml
+++ b/phoenix-pherf/pom.xml
@@ -88,6 +88,20 @@
 			<artifactId>system-rules</artifactId>
 			<version>1.8.0</version>
 		</dependency>
+		<dependency>
+			<groupId>org.apache.hbase</groupId>
+			<artifactId>hbase-testing-util</artifactId>
+			<version>${hbase.version}</version>
+			<scope>test</scope>
+			<optional>true</optional>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.hbase</groupId>
+			<artifactId>hbase-it</artifactId>
+			<version>${hbase.version}</version>
+			<type>test-jar</type>
+			<scope>test</scope>
+		</dependency>
 	</dependencies>
 
 	<build>


[31/40] phoenix git commit: PHOENIX-2142 Implement octet_length build-in function for BINARY and VARBINARY(Shuxiong Ye)

Posted by ma...@apache.org.
PHOENIX-2142 Implement octet_length build-in function for BINARY and VARBINARY(Shuxiong Ye)


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/274eb42d
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/274eb42d
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/274eb42d

Branch: refs/heads/calcite
Commit: 274eb42d41c3c545f28491d845ec6e0b20bdbe5b
Parents: c435bba
Author: Samarth <sa...@salesforce.com>
Authored: Wed Aug 12 09:00:57 2015 -0700
Committer: Samarth <sa...@salesforce.com>
Committed: Wed Aug 12 09:00:57 2015 -0700

----------------------------------------------------------------------
 .../end2end/OctetLengthFunctionEnd2EndIT.java   | 73 ++++++++++++++++++++
 .../phoenix/expression/ExpressionType.java      |  4 +-
 .../function/OctetLengthFunction.java           | 66 ++++++++++++++++++
 .../phoenix/schema/types/PBinaryBase.java       | 12 ++++
 .../expression/OctetLengthFunctionTest.java     | 67 ++++++++++++++++++
 5 files changed, 221 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/274eb42d/phoenix-core/src/it/java/org/apache/phoenix/end2end/OctetLengthFunctionEnd2EndIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/OctetLengthFunctionEnd2EndIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/OctetLengthFunctionEnd2EndIT.java
new file mode 100644
index 0000000..1239e7a
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/OctetLengthFunctionEnd2EndIT.java
@@ -0,0 +1,73 @@
+/*
+ * 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.phoenix.end2end;
+
+import static org.apache.phoenix.util.TestUtil.closeStmtAndConn;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+
+import org.apache.phoenix.expression.function.OctetLengthFunction;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * End to end tests for {@link OctetLengthFunction}
+ */
+public class OctetLengthFunctionEnd2EndIT extends BaseHBaseManagedTimeIT {
+
+    private static final String KEY = "key";
+
+    @Before
+    public void initTable() throws Exception {
+        Connection conn = null;
+        PreparedStatement stmt = null;
+        try {
+            conn = DriverManager.getConnection(getUrl());
+            String ddl;
+            ddl = "CREATE TABLE ta (k VARCHAR NOT NULL PRIMARY KEY, b BINARY(4), vb VARBINARY)";
+            conn.createStatement().execute(ddl);
+            conn.commit();
+        } finally {
+            closeStmtAndConn(stmt, conn);
+        }
+    }
+
+    @Test
+    public void test() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO ta VALUES (?, ?, ?)");
+        stmt.setString(1, KEY);
+        stmt.setBytes(2, new byte[] { 1, 2, 3, 4 });
+        stmt.setBytes(3, new byte[] { 1, 2, 3, 4 });
+        stmt.executeUpdate();
+        conn.commit();
+        ResultSet rs =
+                conn.createStatement()
+                        .executeQuery(
+                            "SELECT OCTET_LENGTH(vb), OCTET_LENGTH(b) FROM ta WHERE OCTET_LENGTH(vb)=4 and OCTET_LENGTH(b)=4");
+        assertTrue(rs.next());
+        assertEquals(4, rs.getInt(1));
+        assertEquals(4, rs.getInt(2));
+        assertTrue(!rs.next());
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/274eb42d/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
index 5dbab69..dbe2509 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
@@ -72,6 +72,7 @@ import org.apache.phoenix.expression.function.MinuteFunction;
 import org.apache.phoenix.expression.function.MonthFunction;
 import org.apache.phoenix.expression.function.NowFunction;
 import org.apache.phoenix.expression.function.NthValueFunction;
+import org.apache.phoenix.expression.function.OctetLengthFunction;
 import org.apache.phoenix.expression.function.PercentRankAggregateFunction;
 import org.apache.phoenix.expression.function.PercentileContAggregateFunction;
 import org.apache.phoenix.expression.function.PercentileDiscAggregateFunction;
@@ -261,7 +262,8 @@ public enum ExpressionType {
     GetByteFunction(GetByteFunction.class),
     SetByteFunction(SetByteFunction.class),
     GetBitFunction(GetBitFunction.class),
-    SetBitFunction(SetBitFunction.class)
+    SetBitFunction(SetBitFunction.class),
+    OctetLengthFunction(OctetLengthFunction.class),
     ;
 
     ExpressionType(Class<? extends Expression> clazz) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/274eb42d/phoenix-core/src/main/java/org/apache/phoenix/expression/function/OctetLengthFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/OctetLengthFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/OctetLengthFunction.java
new file mode 100644
index 0000000..ef20734
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/OctetLengthFunction.java
@@ -0,0 +1,66 @@
+/*
+ * 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.phoenix.expression.function;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.PBinary;
+import org.apache.phoenix.schema.types.PBinaryBase;
+import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PInteger;
+import org.apache.phoenix.schema.types.PVarbinary;
+
+@BuiltInFunction(name = OctetLengthFunction.NAME, args = { @Argument(allowedTypes = {
+        PBinary.class, PVarbinary.class }), })
+public class OctetLengthFunction extends ScalarFunction {
+
+    public static final String NAME = "OCTET_LENGTH";
+
+    public OctetLengthFunction() {
+    }
+
+    public OctetLengthFunction(List<Expression> children) throws SQLException {
+        super(children);
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        // get binary data parameter
+        Expression dataExpr = children.get(0);
+        if (!dataExpr.evaluate(tuple, ptr)) return false;
+        // set result
+        ((PBinaryBase) dataExpr.getDataType()).octetLength(ptr, dataExpr.getSortOrder(), ptr);
+        return true;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PInteger.INSTANCE;
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/274eb42d/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryBase.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryBase.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryBase.java
index ec0793e..0ad4ce1 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryBase.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryBase.java
@@ -83,4 +83,16 @@ public abstract class PBinaryBase extends PDataType<byte[]> {
         ret = (byte) ((ret & (~(1 << (off % Byte.SIZE)))) | (newValue << (off % Byte.SIZE)));
         setByte(bytes, offset, length, sortOrder, off / Byte.SIZE, ret, outPtr);
     }
+
+    public void octetLength(ImmutableBytesWritable ptr, SortOrder sortOrder,
+            ImmutableBytesWritable outPtr) {
+        octetLength(ptr.get(), ptr.getOffset(), ptr.getLength(), sortOrder, outPtr);
+    }
+
+    public void octetLength(byte[] bytes, int offset, int length, SortOrder sortOrder,
+            ImmutableBytesWritable outPtr) {
+        bytes = new byte[PInteger.INSTANCE.getByteSize()];
+        PInteger.INSTANCE.getCodec().encodeInt(length, bytes, 0);
+        outPtr.set(bytes);
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/274eb42d/phoenix-core/src/test/java/org/apache/phoenix/expression/OctetLengthFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/OctetLengthFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/OctetLengthFunctionTest.java
new file mode 100644
index 0000000..9211777
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/OctetLengthFunctionTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.phoenix.expression;
+
+import static org.junit.Assert.assertEquals;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.function.OctetLengthFunction;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.types.PBinary;
+import org.apache.phoenix.schema.types.PBinaryBase;
+import org.apache.phoenix.schema.types.PVarbinary;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Unit tests for {@link OctetLengthFunction}
+ */
+public class OctetLengthFunctionTest {
+    private void testOctetLengthExpression(Expression data, int expected) throws SQLException {
+        List<Expression> expressions = Lists.newArrayList(data);
+        Expression octetLengthFunction = new OctetLengthFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        octetLengthFunction.evaluate(null, ptr);
+        Integer result =
+                (Integer) octetLengthFunction.getDataType().toObject(ptr,
+                    octetLengthFunction.getSortOrder());
+        assertEquals(expected, result.intValue());
+    }
+
+    private void testOctetLength(byte[] bytes, PBinaryBase dataType, int expected)
+            throws SQLException {
+        LiteralExpression dataExpr;
+        dataExpr = LiteralExpression.newConstant(bytes, dataType, SortOrder.ASC);
+        testOctetLengthExpression(dataExpr, expected);
+        dataExpr = LiteralExpression.newConstant(bytes, dataType, SortOrder.DESC);
+        testOctetLengthExpression(dataExpr, expected);
+    }
+
+    @Test
+    public void testByteBatch() throws SQLException {
+        for (int len = 0; len < 300; ++len) {
+            byte[] bytes = new byte[len];
+            testOctetLength(bytes, PBinary.INSTANCE, bytes.length);
+            testOctetLength(bytes, PVarbinary.INSTANCE, bytes.length);
+        }
+    }
+}


[22/40] phoenix git commit: Post release - Set version to 4.6.0-HBase-1.1-SNAPSHOT

Posted by ma...@apache.org.
Post release - Set version to 4.6.0-HBase-1.1-SNAPSHOT


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/7e21b8b9
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/7e21b8b9
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/7e21b8b9

Branch: refs/heads/calcite
Commit: 7e21b8b9893284750f6573f867c73d132f120183
Parents: 265b6de
Author: Mujtaba <mu...@apache.org>
Authored: Tue Jul 28 10:23:49 2015 -0700
Committer: Mujtaba <mu...@apache.org>
Committed: Tue Jul 28 10:23:49 2015 -0700

----------------------------------------------------------------------
 phoenix-assembly/pom.xml      | 2 +-
 phoenix-core/pom.xml          | 2 +-
 phoenix-flume/pom.xml         | 2 +-
 phoenix-pherf/pom.xml         | 2 +-
 phoenix-pig/pom.xml           | 2 +-
 phoenix-server-client/pom.xml | 2 +-
 phoenix-server/pom.xml        | 2 +-
 phoenix-spark/pom.xml         | 2 +-
 pom.xml                       | 2 +-
 9 files changed, 9 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e21b8b9/phoenix-assembly/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-assembly/pom.xml b/phoenix-assembly/pom.xml
index 962e08e..293e907 100644
--- a/phoenix-assembly/pom.xml
+++ b/phoenix-assembly/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix</artifactId>
-    <version>4.5.0-HBase-1.1</version>
+    <version>4.6.0-HBase-1.1-SNAPSHOT</version>
   </parent>
   <artifactId>phoenix-assembly</artifactId>
   <name>Phoenix Assembly</name>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e21b8b9/phoenix-core/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-core/pom.xml b/phoenix-core/pom.xml
index 3288f49..6fc1171 100644
--- a/phoenix-core/pom.xml
+++ b/phoenix-core/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix</artifactId>
-    <version>4.5.0-HBase-1.1</version>
+    <version>4.6.0-HBase-1.1-SNAPSHOT</version>
   </parent>
   <artifactId>phoenix-core</artifactId>
   <name>Phoenix Core</name>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e21b8b9/phoenix-flume/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-flume/pom.xml b/phoenix-flume/pom.xml
index 0f65f2d..2e1fa13 100644
--- a/phoenix-flume/pom.xml
+++ b/phoenix-flume/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix</artifactId>
-    <version>4.5.0-HBase-1.1</version>
+    <version>4.6.0-HBase-1.1-SNAPSHOT</version>
   </parent>
   <artifactId>phoenix-flume</artifactId>
   <name>Phoenix - Flume</name>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e21b8b9/phoenix-pherf/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-pherf/pom.xml b/phoenix-pherf/pom.xml
index b734e4d..66b949b 100644
--- a/phoenix-pherf/pom.xml
+++ b/phoenix-pherf/pom.xml
@@ -15,7 +15,7 @@
 	<parent>
 		<groupId>org.apache.phoenix</groupId>
 		<artifactId>phoenix</artifactId>
-		<version>4.5.0-HBase-1.1</version>
+		<version>4.6.0-HBase-1.1-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>phoenix-pherf</artifactId>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e21b8b9/phoenix-pig/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-pig/pom.xml b/phoenix-pig/pom.xml
index 5370558..00f6954 100644
--- a/phoenix-pig/pom.xml
+++ b/phoenix-pig/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix</artifactId>
-    <version>4.5.0-HBase-1.1</version>
+    <version>4.6.0-HBase-1.1-SNAPSHOT</version>
   </parent>
   <artifactId>phoenix-pig</artifactId>
   <name>Phoenix - Pig</name>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e21b8b9/phoenix-server-client/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-server-client/pom.xml b/phoenix-server-client/pom.xml
index cea07fd..266885d 100644
--- a/phoenix-server-client/pom.xml
+++ b/phoenix-server-client/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix</artifactId>
-    <version>4.5.0-HBase-1.1</version>
+    <version>4.6.0-HBase-1.1-SNAPSHOT</version>
   </parent>
   <artifactId>phoenix-server-client</artifactId>
   <name>Phoenix Query Server Client</name>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e21b8b9/phoenix-server/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-server/pom.xml b/phoenix-server/pom.xml
index 41cc123..a4f517a 100644
--- a/phoenix-server/pom.xml
+++ b/phoenix-server/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix</artifactId>
-    <version>4.5.0-HBase-1.1</version>
+    <version>4.6.0-HBase-1.1-SNAPSHOT</version>
   </parent>
   <artifactId>phoenix-server</artifactId>
   <name>Phoenix Query Server</name>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e21b8b9/phoenix-spark/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-spark/pom.xml b/phoenix-spark/pom.xml
index 6269f3d..4287bf1 100644
--- a/phoenix-spark/pom.xml
+++ b/phoenix-spark/pom.xml
@@ -28,7 +28,7 @@
   <parent>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix</artifactId>
-    <version>4.5.0-HBase-1.1</version>
+    <version>4.6.0-HBase-1.1-SNAPSHOT</version>
   </parent>
   <artifactId>phoenix-spark</artifactId>
   <name>Phoenix - Spark</name>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e21b8b9/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 2e2c6c2..ac0e5c7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.apache.phoenix</groupId>
   <artifactId>phoenix</artifactId>
-  <version>4.5.0-HBase-1.1</version>
+  <version>4.6.0-HBase-1.1-SNAPSHOT</version>
   <packaging>pom</packaging>
   <name>Apache Phoenix</name>
   <description>A SQL layer over HBase</description>


[14/40] phoenix git commit: Fix Apache RAT warnings

Posted by ma...@apache.org.
Fix Apache RAT warnings


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/18fefed6
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/18fefed6
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/18fefed6

Branch: refs/heads/calcite
Commit: 18fefed64f1a3194e70915e369da9956b8d75ae9
Parents: 5076052
Author: Mujtaba <mu...@apache.org>
Authored: Wed Jul 22 20:57:41 2015 -0700
Committer: Mujtaba <mu...@apache.org>
Committed: Wed Jul 22 20:57:41 2015 -0700

----------------------------------------------------------------------
 .../org/apache/phoenix/rpc/UpdateCacheIT.java    | 17 +++++++++++++++++
 .../phoenix/compile/ListJarsQueryPlan.java       | 17 +++++++++++++++++
 .../expression/function/ArrayFillFunction.java   | 17 +++++++++++++++++
 .../apache/phoenix/parse/DeleteJarStatement.java | 17 +++++++++++++++++
 .../phoenix/schema/SequenceAllocation.java       | 19 ++++++++++++++++++-
 .../phoenix/schema/SequenceAllocationTest.java   | 17 +++++++++++++++++
 .../apache/phoenix/pherf/workload/Workload.java  | 17 +++++++++++++++++
 .../phoenix/pig/udf/ReserveNSequenceTestIT.java  | 16 +++++++++++++++-
 8 files changed, 135 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/18fefed6/phoenix-core/src/it/java/org/apache/phoenix/rpc/UpdateCacheIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/rpc/UpdateCacheIT.java b/phoenix-core/src/it/java/org/apache/phoenix/rpc/UpdateCacheIT.java
index c657e41..b7f880a 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/rpc/UpdateCacheIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/rpc/UpdateCacheIT.java
@@ -1,3 +1,20 @@
+/**
+ * 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.phoenix.rpc;
 
 import static org.apache.phoenix.util.TestUtil.INDEX_DATA_SCHEMA;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/18fefed6/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java
index 9fdf35b..928bdef 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java
@@ -1,3 +1,20 @@
+/**
+ * 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.phoenix.compile;
 
 import java.io.IOException;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/18fefed6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayFillFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayFillFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayFillFunction.java
index 5c3a2e5..c8db7f9 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayFillFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayFillFunction.java
@@ -1,3 +1,20 @@
+/**
+ * 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.phoenix.expression.function;
 
 import java.util.Arrays;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/18fefed6/phoenix-core/src/main/java/org/apache/phoenix/parse/DeleteJarStatement.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/DeleteJarStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/DeleteJarStatement.java
index 7ccdc72..a7438ef 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/DeleteJarStatement.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/DeleteJarStatement.java
@@ -1,3 +1,20 @@
+/**
+ * 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.phoenix.parse;
 
 public class DeleteJarStatement extends MutableStatement {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/18fefed6/phoenix-core/src/main/java/org/apache/phoenix/schema/SequenceAllocation.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/SequenceAllocation.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/SequenceAllocation.java
index afb4a20..af87e56 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/SequenceAllocation.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/SequenceAllocation.java
@@ -1,3 +1,20 @@
+/**
+ * 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.phoenix.schema;
 
 /**
@@ -45,4 +62,4 @@ public class SequenceAllocation implements Comparable<SequenceAllocation> {
         return sequenceKey.compareTo(that.sequenceKey);
     }
     
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/18fefed6/phoenix-core/src/test/java/org/apache/phoenix/schema/SequenceAllocationTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/schema/SequenceAllocationTest.java b/phoenix-core/src/test/java/org/apache/phoenix/schema/SequenceAllocationTest.java
index 4a825f2..2b435bf 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/schema/SequenceAllocationTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/schema/SequenceAllocationTest.java
@@ -1,3 +1,20 @@
+/**
+ * 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.phoenix.schema;
 
 import static org.junit.Assert.assertEquals;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/18fefed6/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/Workload.java
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/Workload.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/Workload.java
index 16a493e..882fa50 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/Workload.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/Workload.java
@@ -1,3 +1,20 @@
+/**
+ * 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.phoenix.pherf.workload;
 
 public interface Workload {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/18fefed6/phoenix-pig/src/it/java/org/apache/phoenix/pig/udf/ReserveNSequenceTestIT.java
----------------------------------------------------------------------
diff --git a/phoenix-pig/src/it/java/org/apache/phoenix/pig/udf/ReserveNSequenceTestIT.java b/phoenix-pig/src/it/java/org/apache/phoenix/pig/udf/ReserveNSequenceTestIT.java
index 2cbb6cc..05c7c82 100644
--- a/phoenix-pig/src/it/java/org/apache/phoenix/pig/udf/ReserveNSequenceTestIT.java
+++ b/phoenix-pig/src/it/java/org/apache/phoenix/pig/udf/ReserveNSequenceTestIT.java
@@ -1,5 +1,19 @@
 /**
- * 
+ * 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.phoenix.pig.udf;
 


[23/40] phoenix git commit: PHOENIX-2155 Add gpg signing to release profile

Posted by ma...@apache.org.
PHOENIX-2155 Add gpg signing to release profile


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/e4ed2d9f
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/e4ed2d9f
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/e4ed2d9f

Branch: refs/heads/calcite
Commit: e4ed2d9f6f046ebc510ab3c78a1b3b8a9c39d0aa
Parents: 7e21b8b
Author: Mujtaba <mu...@apache.org>
Authored: Wed Jul 29 13:06:52 2015 -0700
Committer: Mujtaba <mu...@apache.org>
Committed: Wed Jul 29 13:06:52 2015 -0700

----------------------------------------------------------------------
 pom.xml | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/e4ed2d9f/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index ac0e5c7..bda6628 100644
--- a/pom.xml
+++ b/pom.xml
@@ -788,9 +788,22 @@
               </execution>
             </executions>
           </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-gpg-plugin</artifactId>
+            <version>1.6</version>
+            <executions>
+              <execution>
+              <id>sign-artifacts</id>
+              <phase>verify</phase>
+                <goals>
+                  <goal>sign</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
         </plugins>
       </build>
     </profile>
-
   </profiles>
 </project>


[36/40] phoenix git commit: PHOENIX-2181: PhoenixHBaseLoader doesn't work with salted tables

Posted by ma...@apache.org.
PHOENIX-2181: PhoenixHBaseLoader doesn't work with salted tables


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/c6a3d6f9
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/c6a3d6f9
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/c6a3d6f9

Branch: refs/heads/calcite
Commit: c6a3d6f9ced2aeb6dadb44b899368d3da1a3b6ae
Parents: 8a1566c
Author: Ravi Magham <ra...@bazaarvoice.com>
Authored: Fri Aug 14 14:19:16 2015 -0700
Committer: Ravi Magham <ra...@bazaarvoice.com>
Committed: Fri Aug 14 14:19:16 2015 -0700

----------------------------------------------------------------------
 .../org/apache/phoenix/util/PhoenixRuntime.java |  4 +-
 .../phoenix/pig/PhoenixHBaseLoaderIT.java       | 47 ++++++++++++++++++++
 2 files changed, 50 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/c6a3d6f9/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java b/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
index 586cedd..4f87765 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
@@ -386,7 +386,9 @@ public class PhoenixRuntime {
         Set<String> unresolvedColumnNames = new TreeSet<String>();
         if (columns == null || columns.isEmpty()) {
             // use all columns in the table
-            for(PColumn pColumn : table.getColumns()) {
+        	int offset = (table.getBucketNum() == null ? 0 : 1);
+        	for (int i = offset; i < table.getColumns().size(); i++) {
+        	   PColumn pColumn = table.getColumns().get(i);
                int sqlType = pColumn.getDataType().getSqlType();
                columnInfoList.add(new ColumnInfo(pColumn.toString(), sqlType)); 
             }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c6a3d6f9/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
----------------------------------------------------------------------
diff --git a/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java b/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
index 53a62ee..25458d6 100644
--- a/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
+++ b/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
@@ -582,6 +582,53 @@ public class PhoenixHBaseLoaderIT extends BaseHBaseManagedTimeIT {
           dropTable(INDEX_NAME);
         }
     }
+	 
+	@Test 
+	public void testLoadOfSaltTable() throws Exception {
+	    final String TABLE = "TABLE11";
+        final String sourceTableddl = "CREATE TABLE  " + TABLE
+                + "  (ID  INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR, AGE INTEGER, SAL INTEGER) SALT_BUCKETS=2  ";
+         
+        conn.createStatement().execute(sourceTableddl);
+        
+        //prepare data with 10 rows having age 25 and the other 30.
+        final String dml = "UPSERT INTO " + TABLE + " VALUES(?,?,?,?)";
+        PreparedStatement stmt = conn.prepareStatement(dml);
+        int rows = 20;
+        int j = 0, k = 0;
+        for(int i = 0 ; i < rows; i++) {
+            stmt.setInt(1, i);
+            stmt.setString(2, "a"+i);
+            if(i % 2 == 0) {
+                stmt.setInt(3, 25);
+                stmt.setInt(4, 10 * 2 * j++);    
+            } else {
+                stmt.setInt(3, 30);
+                stmt.setInt(4, 10 * 3 * k++);
+            }
+            
+            stmt.execute();    
+        }
+        conn.commit();
+            
+        final Data data = Storage.resetData(pigServer);
+        List<Tuple> expectedList = new ArrayList<Tuple>();
+        expectedList.add(Storage.tuple(25,10));
+        expectedList.add(Storage.tuple(30,10));
+        
+        pigServer.setBatchOn();
+        pigServer.registerQuery(String.format(
+                "A = load 'hbase://table/%s' using " + PhoenixHBaseLoader.class.getName() + "('%s');", TABLE,
+                zkQuorum));
+        
+        pigServer.registerQuery("B = GROUP A BY AGE;");
+        pigServer.registerQuery("C = FOREACH B GENERATE group,COUNT(A);");
+        pigServer.registerQuery("STORE C INTO 'out' using mock.Storage();");
+        pigServer.executeBatch();
+        
+        List<Tuple> actualList = data.get("out");
+        assertEquals(expectedList.size(), actualList.size());
+	}
     
     @After
     public void tearDown() throws Exception {


[18/40] phoenix git commit: PHOENIX-2138 Non equality comparisons don't work for ARRAY type columns that are DESC in row key (Dumindu Buddhika)

Posted by ma...@apache.org.
PHOENIX-2138 Non equality comparisons don't work for ARRAY type columns
that are DESC in row key (Dumindu Buddhika)


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/69f22b51
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/69f22b51
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/69f22b51

Branch: refs/heads/calcite
Commit: 69f22b5151e40645b4968a787e55d0155b128855
Parents: ce89805
Author: ramkrishna <ra...@gmail.com>
Authored: Sun Jul 26 12:06:11 2015 +0530
Committer: ramkrishna <ra...@gmail.com>
Committed: Sun Jul 26 12:08:59 2015 +0530

----------------------------------------------------------------------
 .../org/apache/phoenix/end2end/ArrayIT.java     | 201 ++++++++++++++++++-
 .../apache/phoenix/iterate/ExplainTable.java    |   4 +-
 .../phoenix/schema/types/PArrayDataType.java    |   9 +-
 .../phoenix/schema/types/PhoenixArray.java      |   4 -
 4 files changed, 209 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/69f22b51/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java
index 89997f4..800a7b4 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java
@@ -2038,5 +2038,204 @@ public class ArrayIT extends BaseClientManagedTimeIT {
         assertFalse(rs.next());
         conn.close();
     }
-    
+
+    @Test
+    public void testComparisonOperatorsForDesc1()throws Exception{
+        long ts = nextTimestamp();
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 10));
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        String ddl = "create table a (k varchar array primary key desc)";
+        conn.createStatement().execute(ddl);
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 30));
+        conn = DriverManager.getConnection(getUrl(), props);
+        PreparedStatement stmt = conn.prepareStatement("upsert into a values (array['a', 'c'])");
+        stmt.execute();
+        conn.commit();
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 40));
+        conn = DriverManager.getConnection(getUrl(), props);
+        ResultSet rs;
+        stmt = conn.prepareStatement("select * from a where k >= array['a', 'b']");
+        rs = stmt.executeQuery();
+        assertTrue(rs.next());
+    }
+
+    @Test
+    public void testComparisonOperatorsForDesc2()throws Exception{
+        long ts = nextTimestamp();
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 10));
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        String ddl = "create table a (k varchar array primary key desc)";
+        conn.createStatement().execute(ddl);
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 30));
+        conn = DriverManager.getConnection(getUrl(), props);
+        PreparedStatement stmt = conn.prepareStatement("upsert into a values (array['a', 'c'])");
+        stmt.execute();
+        conn.commit();
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 40));
+        conn = DriverManager.getConnection(getUrl(), props);
+        ResultSet rs;
+        stmt = conn.prepareStatement("select * from a where k >= array['a', 'c']");
+        rs = stmt.executeQuery();
+        assertTrue(rs.next());
+    }
+
+    @Test
+    public void testComparisonOperatorsForDesc3()throws Exception{
+        long ts = nextTimestamp();
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 10));
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        String ddl = "create table a (k varchar array primary key desc)";
+        conn.createStatement().execute(ddl);
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 30));
+        conn = DriverManager.getConnection(getUrl(), props);
+        PreparedStatement stmt = conn.prepareStatement("upsert into a values (array['a', 'c'])");
+        stmt.execute();
+        conn.commit();
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 40));
+        conn = DriverManager.getConnection(getUrl(), props);
+        ResultSet rs;
+        stmt = conn.prepareStatement("select * from a where k > array['a', 'b']");
+        rs = stmt.executeQuery();
+        assertTrue(rs.next());
+    }
+
+    @Test
+    public void testComparisonOperatorsForDesc4()throws Exception{
+        long ts = nextTimestamp();
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 10));
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        String ddl = "create table a (k varchar array primary key desc)";
+        conn.createStatement().execute(ddl);
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 30));
+        conn = DriverManager.getConnection(getUrl(), props);
+        PreparedStatement stmt = conn.prepareStatement("upsert into a values (array['a', 'b'])");
+        stmt.execute();
+        conn.commit();
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 40));
+        conn = DriverManager.getConnection(getUrl(), props);
+        ResultSet rs;
+        stmt = conn.prepareStatement("select * from a where k <= array['a', 'c']");
+        rs = stmt.executeQuery();
+        assertTrue(rs.next());
+    }
+
+    @Test
+    public void testComparisonOperatorsForDesc5()throws Exception{
+        long ts = nextTimestamp();
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 10));
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        String ddl = "create table a (k varchar array primary key desc)";
+        conn.createStatement().execute(ddl);
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 30));
+        conn = DriverManager.getConnection(getUrl(), props);
+        PreparedStatement stmt = conn.prepareStatement("upsert into a values (array['a', 'b'])");
+        stmt.execute();
+        conn.commit();
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 40));
+        conn = DriverManager.getConnection(getUrl(), props);
+        ResultSet rs;
+        stmt = conn.prepareStatement("select * from a where k <= array['a', 'b']");
+        rs = stmt.executeQuery();
+        assertTrue(rs.next());
+    }
+
+    @Test
+    public void testComparisonOperatorsForDesc6()throws Exception{
+        long ts = nextTimestamp();
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 10));
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        String ddl = "create table a (k varchar array primary key desc)";
+        conn.createStatement().execute(ddl);
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 30));
+        conn = DriverManager.getConnection(getUrl(), props);
+        PreparedStatement stmt = conn.prepareStatement("upsert into a values (array['a', 'b'])");
+        stmt.execute();
+        conn.commit();
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 40));
+        conn = DriverManager.getConnection(getUrl(), props);
+        ResultSet rs;
+        stmt = conn.prepareStatement("select * from a where k < array['a', 'c']");
+        rs = stmt.executeQuery();
+        assertTrue(rs.next());
+    }
+
+    @Test
+    public void testComparisonOperatorsForDesc7()throws Exception{
+        long ts = nextTimestamp();
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 10));
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        String ddl = "create table a (k integer array primary key desc)";
+        conn.createStatement().execute(ddl);
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 30));
+        conn = DriverManager.getConnection(getUrl(), props);
+        PreparedStatement stmt = conn.prepareStatement("upsert into a values (array[1, 2])");
+        stmt.execute();
+        conn.commit();
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 40));
+        conn = DriverManager.getConnection(getUrl(), props);
+        ResultSet rs;
+        stmt = conn.prepareStatement("select * from a where k < array[1, 4]");
+        rs = stmt.executeQuery();
+        assertTrue(rs.next());
+    }
+
+    @Test
+    public void testComparisonOperatorsForDesc8()throws Exception{
+        long ts = nextTimestamp();
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 10));
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        String ddl = "create table a (k integer array primary key desc)";
+        conn.createStatement().execute(ddl);
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 30));
+        conn = DriverManager.getConnection(getUrl(), props);
+        PreparedStatement stmt = conn.prepareStatement("upsert into a values (array[1, 2])");
+        stmt.execute();
+        conn.commit();
+        conn.close();
+
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 40));
+        conn = DriverManager.getConnection(getUrl(), props);
+        ResultSet rs;
+        stmt = conn.prepareStatement("select * from a where k <= array[1, 2]");
+        rs = stmt.executeQuery();
+        assertTrue(rs.next());
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/69f22b51/phoenix-core/src/main/java/org/apache/phoenix/iterate/ExplainTable.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ExplainTable.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ExplainTable.java
index 3fe42fa..e3eb51b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ExplainTable.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ExplainTable.java
@@ -176,7 +176,9 @@ public abstract class ExplainTable {
         SortOrder sortOrder = tableRef.getTable().getPKColumns().get(slotIndex).getSortOrder();
         if (sortOrder == SortOrder.DESC) {
             buf.append('~');
-            range = SortOrder.invert(range, 0, new byte[range.length], 0, range.length);
+            ImmutableBytesWritable ptr = new ImmutableBytesWritable(range);
+            type.coerceBytes(ptr, type, sortOrder, SortOrder.getDefault());
+            range = ptr.get();
         }
         Format formatter = context.getConnection().getFormatter(type);
         buf.append(type.toStringLiteral(range, formatter));

http://git-wip-us.apache.org/repos/asf/phoenix/blob/69f22b51/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
index 6236184..28144fd 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
@@ -108,7 +108,8 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
             byteStream = new TrustedByteArrayOutputStream(size + capacity + Bytes.SIZEOF_INT + Bytes.SIZEOF_BYTE
                     + Bytes.SIZEOF_INT);
         } else {
-            int size = arr.getMaxLength() * noOfElements;
+            int elemLength = (arr.getMaxLength() == null ? baseType.getByteSize() : arr.getMaxLength());
+            int size = elemLength * noOfElements;
             // Here the int for noofelements, byte for the version
             byteStream = new TrustedByteArrayOutputStream(size);
         }
@@ -301,8 +302,10 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
             }
             baseType = desiredBaseType;
         } else {
-            pArr = (PhoenixArray)value;
-            pArr = new PhoenixArray(pArr, desiredMaxLength);
+            pArr = (PhoenixArray) value;
+            if (!Objects.equal(maxLength, desiredMaxLength)) {
+                pArr = new PhoenixArray(pArr, desiredMaxLength);
+            }
         }
         ptr.set(toBytes(pArr, baseType, desiredSortOrder, expectedRowKeyOrderOptimizable));
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/69f22b51/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PhoenixArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PhoenixArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PhoenixArray.java
index 843c831..3dc1050 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PhoenixArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PhoenixArray.java
@@ -111,8 +111,6 @@ public class PhoenixArray implements Array,SQLCloseable {
                         }
                     }
     		    }
-		    } else {
-		        maxLength = baseType.getByteSize();
 		    }
 		}
     this.array = convertObjectArrayToPrimitiveArray(elements);
@@ -126,8 +124,6 @@ public class PhoenixArray implements Array,SQLCloseable {
             if (baseType.getByteSize() == null) {
                 elements = coerceToNewLength(baseType, (Object[])pArr.array, desiredMaxLength);
                 maxLength = desiredMaxLength;
-            } else {
-                maxLength = baseType.getByteSize();
             }
         }
         this.array = convertObjectArrayToPrimitiveArray(elements);


[16/40] phoenix git commit: PHOENIX-2132 Pherf - Fix drop all command and execution from Eclipse/IDE

Posted by ma...@apache.org.
PHOENIX-2132 Pherf - Fix drop all command and execution from Eclipse/IDE


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/c65ef907
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/c65ef907
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/c65ef907

Branch: refs/heads/calcite
Commit: c65ef907f4c2e8edbcc563e2fea3decca41c4fe9
Parents: b7cd7e5
Author: Mujtaba <mu...@apache.org>
Authored: Fri Jul 24 11:18:52 2015 -0700
Committer: Mujtaba <mu...@apache.org>
Committed: Fri Jul 24 11:18:52 2015 -0700

----------------------------------------------------------------------
 phoenix-pherf/pom.xml                           | 25 ++++++---
 .../apache/phoenix/pherf/util/PhoenixUtil.java  | 55 +++++++++++++++-----
 2 files changed, 60 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/c65ef907/phoenix-pherf/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-pherf/pom.xml b/phoenix-pherf/pom.xml
index 8343be0..e08670c 100644
--- a/phoenix-pherf/pom.xml
+++ b/phoenix-pherf/pom.xml
@@ -69,7 +69,6 @@
 		<dependency>
 			<groupId>junit</groupId>
 			<artifactId>junit</artifactId>
-			<version>4.11</version>
 			<scope>test</scope>
 		</dependency>
 		<dependency>
@@ -91,14 +90,12 @@
 		<dependency>
 			<groupId>org.apache.hbase</groupId>
 			<artifactId>hbase-testing-util</artifactId>
-			<version>${hbase.version}</version>
 			<scope>test</scope>
 			<optional>true</optional>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.hbase</groupId>
 			<artifactId>hbase-it</artifactId>
-			<version>${hbase.version}</version>
 			<type>test-jar</type>
 			<scope>test</scope>
 		</dependency>
@@ -109,6 +106,12 @@
 			<resource>
 				<directory>src/main/resources</directory>
 			</resource>
+			<resource>
+				<directory>config</directory>
+				<includes>
+					<include>**/*.properties</include>
+				</includes>
+			</resource>
 		</resources>
 		<testResources>
 			<testResource>
@@ -129,13 +132,11 @@
 			</plugin>
 			<plugin>
 				<artifactId>maven-dependency-plugin</artifactId>
-				<version>${maven-dependency-plugin.version}</version>
 			</plugin>
 
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-compiler-plugin</artifactId>
-				<version>3.1</version>
 				<configuration>
 					<source>1.7</source>
 					<target>1.7</target>
@@ -177,17 +178,27 @@
 						</goals>
 						<configuration>
 							<descriptors>
-							    <!-- Produces minimal Pherf jar -->
+								<!-- Produces minimal Pherf jar -->
 								<descriptor>src/main/assembly/minimal.xml</descriptor>
 								<!-- Produces standalone zip that bundles all required dependencies -->
 								<descriptor>src/main/assembly/standalone.xml</descriptor>
-								<!-- Produces cluster zip with minimal Pherf jar. Setting HBase classpath in env.sh is required for this configuration -->								
+								<!-- Produces cluster zip with minimal Pherf jar. Setting HBase classpath 
+									in env.sh is required for this configuration -->
 								<descriptor>src/main/assembly/cluster.xml</descriptor>
 							</descriptors>
 						</configuration>
 					</execution>
 				</executions>
 			</plugin>
+			<plugin>
+				<groupId>org.apache.rat</groupId>
+				<artifactId>apache-rat-plugin</artifactId>
+				<configuration>
+					<excludes>
+						<exclude>RESULTS/**</exclude>
+					</excludes>
+				</configuration>
+			</plugin>
 		</plugins>
 	</build>
 </project>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c65ef907/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/util/PhoenixUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/util/PhoenixUtil.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/util/PhoenixUtil.java
index 0156149..5f7d637 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/util/PhoenixUtil.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/util/PhoenixUtil.java
@@ -22,19 +22,17 @@ import org.apache.phoenix.pherf.PherfConstants;
 import org.apache.phoenix.pherf.configuration.Column;
 import org.apache.phoenix.pherf.configuration.DataTypeMapping;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
 import java.sql.*;
 import java.util.*;
 
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.HBaseConfiguration;
 import org.apache.phoenix.pherf.configuration.Query;
 import org.apache.phoenix.pherf.configuration.QuerySet;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_SCHEM;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_NAME;
+
 // TODO This class needs to be cleanup up a bit. I just wanted to get an initial placeholder in.
 public class PhoenixUtil {
 	private static final Logger logger = LoggerFactory.getLogger(PhoenixUtil.class);
@@ -95,6 +93,26 @@ public class PhoenixUtil {
         }
         return result;
     }
+
+    /**
+     * Execute statement
+     * @param sql
+     * @param connection
+     * @return
+     * @throws SQLException
+     */
+    public boolean executeStatementThrowException(String sql, Connection connection) throws SQLException {
+    	boolean result = false;
+    	PreparedStatement preparedStatement = null;
+    	try {
+            preparedStatement = connection.prepareStatement(sql);
+            result = preparedStatement.execute();
+            connection.commit();
+        } finally {
+            preparedStatement.close();
+        }
+        return result;
+    }
     
     public boolean executeStatement(String sql, Connection connection) {
     	boolean result = false;
@@ -139,14 +157,25 @@ public class PhoenixUtil {
     	Connection conn = getConnection();
     	try {
         	ResultSet resultSet = getTableMetaData(PherfConstants.PHERF_SCHEMA_NAME, null, conn);
-	    	while (resultSet.next()) {
-	    		String tableName = resultSet.getString("TABLE_SCHEMA") == null ? resultSet.getString("TABLE_NAME") :
-	    						   resultSet.getString("TABLE_SCHEMA") + "." + resultSet.getString("TABLE_NAME");
-	    		if (tableName.matches(regexMatch)) {
-		    		logger.info("\nDropping " + tableName);
-		    		executeStatement("DROP TABLE " + tableName + " CASCADE", conn);
-	    		}
-	    	}
+			while (resultSet.next()) {
+				String tableName = resultSet.getString(TABLE_SCHEM) == null ? resultSet
+						.getString(TABLE_NAME) : resultSet
+						.getString(TABLE_SCHEM)
+						+ "."
+						+ resultSet.getString(TABLE_NAME);
+				if (tableName.matches(regexMatch)) {
+					logger.info("\nDropping " + tableName);
+					try {
+						executeStatementThrowException("DROP TABLE "
+								+ tableName + " CASCADE", conn);
+					} catch (org.apache.phoenix.schema.TableNotFoundException tnf) {
+						logger.error("Table might be already be deleted via cascade. Schema: "
+								+ tnf.getSchemaName()
+								+ " Table: "
+								+ tnf.getTableName());
+					}
+				}
+			}
     	} finally {
     		conn.close();
     	}


[37/40] phoenix git commit: PHOENIX-2031 - Unable to process timestamp/Date data loaded via Phoenix org.apache.phoenix.pig.PhoenixHBaseLoader(ayingshu)

Posted by ma...@apache.org.
PHOENIX-2031 - Unable to process timestamp/Date data loaded via Phoenix org.apache.phoenix.pig.PhoenixHBaseLoader(ayingshu)


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/0f84104e
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/0f84104e
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/0f84104e

Branch: refs/heads/calcite
Commit: 0f84104e2d8914436bb1c1e5f8fa1d40118d1343
Parents: c6a3d6f
Author: ravimagham <ra...@apache.org>
Authored: Thu Aug 20 21:17:42 2015 -0700
Committer: ravimagham <ra...@apache.org>
Committed: Thu Aug 20 21:17:42 2015 -0700

----------------------------------------------------------------------
 .../phoenix/pig/PhoenixHBaseLoaderIT.java       | 89 +++++++++++++++++++-
 .../org/apache/phoenix/pig/util/TypeUtil.java   |  5 +-
 2 files changed, 91 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/0f84104e/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
----------------------------------------------------------------------
diff --git a/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java b/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
index 25458d6..2f33b5f 100644
--- a/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
+++ b/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
@@ -19,11 +19,11 @@
  */
 package org.apache.phoenix.pig;
 
+import static org.apache.phoenix.util.PhoenixRuntime.JDBC_PROTOCOL_SEPARATOR;
+import static org.apache.phoenix.util.TestUtil.LOCALHOST;
 import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.apache.phoenix.util.PhoenixRuntime.JDBC_PROTOCOL_SEPARATOR;
-import static org.apache.phoenix.util.TestUtil.LOCALHOST;
 
 import java.sql.Connection;
 import java.sql.DriverManager;
@@ -51,6 +51,7 @@ import org.apache.pig.impl.logicalLayer.schema.Schema.FieldSchema;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+
 import com.google.common.base.Preconditions;
 
 /**
@@ -395,6 +396,90 @@ public class PhoenixHBaseLoaderIT extends BaseHBaseManagedTimeIT {
         List<Tuple> actualList = data.get("out");
         assertEquals(expectedList, actualList);
     }
+	 
+    @Test
+    public void testTimestampForSQLQuery() throws Exception {
+        try {
+            //create the table
+            String ddl = "CREATE TABLE TIMESTAMP_T (MYKEY VARCHAR,DATE_STP TIMESTAMP CONSTRAINT PK PRIMARY KEY (MYKEY)) ";
+            conn.createStatement().execute(ddl);
+
+            final String dml = "UPSERT INTO TIMESTAMP_T VALUES('foo',TO_TIMESTAMP('2006-04-12 00:00:00'))";
+            conn.createStatement().execute(dml);
+            conn.commit();
+
+            //sql query
+            final String sqlQuery = " SELECT mykey, year(DATE_STP) FROM TIMESTAMP_T ";
+            pigServer.registerQuery(String.format(
+                "A = load 'hbase://query/%s' using org.apache.phoenix.pig.PhoenixHBaseLoader('%s');", sqlQuery,
+                zkQuorum));
+
+            final Iterator<Tuple> iterator = pigServer.openIterator("A");
+            while (iterator.hasNext()) {
+                Tuple tuple = iterator.next();
+                assertEquals("foo", tuple.get(0));
+                assertEquals(2006, tuple.get(1));
+            }
+        } finally {
+            dropTable("TIMESTAMP_T");
+        }
+    }
+    
+    @Test
+    public void testDateForSQLQuery() throws Exception {
+        try {
+            //create the table
+            String ddl = "CREATE TABLE DATE_T (MYKEY VARCHAR,DATE_STP Date CONSTRAINT PK PRIMARY KEY (MYKEY)) ";
+            conn.createStatement().execute(ddl);
+
+            final String dml = "UPSERT INTO DATE_T VALUES('foo',TO_DATE('2004-03-10 10:00:00'))";
+            conn.createStatement().execute(dml);
+            conn.commit();
+
+            //sql query
+            final String sqlQuery = " SELECT mykey, hour(DATE_STP) FROM DATE_T ";
+            pigServer.registerQuery(String.format(
+                "A = load 'hbase://query/%s' using org.apache.phoenix.pig.PhoenixHBaseLoader('%s');", sqlQuery,
+                zkQuorum));
+
+            final Iterator<Tuple> iterator = pigServer.openIterator("A");
+            while (iterator.hasNext()) {
+                Tuple tuple = iterator.next();
+                assertEquals("foo", tuple.get(0));
+                assertEquals(10, tuple.get(1));
+            }
+        } finally {
+            dropTable("DATE_T");
+        }
+    }
+
+    @Test
+    public void testTimeForSQLQuery() throws Exception {
+        try {
+            //create the table
+            String ddl = "CREATE TABLE TIME_T (MYKEY VARCHAR,DATE_STP TIME CONSTRAINT PK PRIMARY KEY (MYKEY)) ";
+            conn.createStatement().execute(ddl);
+
+            final String dml = "UPSERT INTO TIME_T VALUES('foo',TO_TIME('2008-05-16 00:30:00'))";
+            conn.createStatement().execute(dml);
+            conn.commit();
+
+            //sql query
+            final String sqlQuery = " SELECT mykey, minute(DATE_STP) FROM TIME_T ";
+            pigServer.registerQuery(String.format(
+                "A = load 'hbase://query/%s' using org.apache.phoenix.pig.PhoenixHBaseLoader('%s');", sqlQuery,
+                zkQuorum));
+
+            final Iterator<Tuple> iterator = pigServer.openIterator("A");
+            while (iterator.hasNext()) {
+                Tuple tuple = iterator.next();
+                assertEquals("foo", tuple.get(0));
+                assertEquals(30, tuple.get(1));
+            }
+        } finally {
+            dropTable("TIME_T");
+        }
+    }
     
     /**
      * Tests both  {@link PhoenixHBaseLoader} and {@link PhoenixHBaseStorage} 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/0f84104e/phoenix-pig/src/main/java/org/apache/phoenix/pig/util/TypeUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-pig/src/main/java/org/apache/phoenix/pig/util/TypeUtil.java b/phoenix-pig/src/main/java/org/apache/phoenix/pig/util/TypeUtil.java
index 5820ec6..53d3ae3 100644
--- a/phoenix-pig/src/main/java/org/apache/phoenix/pig/util/TypeUtil.java
+++ b/phoenix-pig/src/main/java/org/apache/phoenix/pig/util/TypeUtil.java
@@ -278,7 +278,10 @@ public final class TypeUtil {
                     tuple.set(i, DataType.toBoolean(object));
                     break;
                 case DataType.DATETIME:
-                    tuple.set(i, DataType.toDateTime(object));
+                    if (object instanceof java.sql.Timestamp)
+                        tuple.set(i,new DateTime(((java.sql.Timestamp)object).getTime()));
+                    else
+                        tuple.set(i,new DateTime(object));
                     break;
                 case DataType.BIGDECIMAL:
                     tuple.set(i, DataType.toBigDecimal(object));


[27/40] phoenix git commit: PHOENIX-1791. Adding ability for Pherf Write Workloads to write to a multi-tenant view.

Posted by ma...@apache.org.
PHOENIX-1791. Adding ability for Pherf Write Workloads to write to a multi-tenant view.


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/c811cf68
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/c811cf68
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/c811cf68

Branch: refs/heads/calcite
Commit: c811cf68752b91585fc9c12741f3be005fefbe2f
Parents: 60500f2
Author: Jan <jf...@salesforce.com>
Authored: Thu Aug 6 11:12:52 2015 -0700
Committer: Cody Marcel <co...@gmail.com>
Committed: Mon Aug 10 10:02:18 2015 -0700

----------------------------------------------------------------------
 .../org/apache/phoenix/pherf/DataIngestIT.java  | 67 +++++++++++++++++---
 .../phoenix/pherf/configuration/Scenario.java   | 25 ++++++--
 .../pherf/configuration/XMLConfigParser.java    | 23 ++++---
 .../apache/phoenix/pherf/util/PhoenixUtil.java  | 30 +++++----
 .../phoenix/pherf/workload/WriteWorkload.java   | 49 +++++++++-----
 .../datamodel/test_schema_mt_table.sql          | 31 +++++++++
 .../resources/datamodel/test_schema_mt_view.sql |  1 +
 .../test/resources/scenario/test_scenario.xml   | 22 +++++++
 8 files changed, 198 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/c811cf68/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/DataIngestIT.java
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/DataIngestIT.java b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/DataIngestIT.java
index 1defbb1..297f882 100644
--- a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/DataIngestIT.java
+++ b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/DataIngestIT.java
@@ -22,6 +22,19 @@ import com.jcabi.jdbc.JdbcSession;
 import com.jcabi.jdbc.Outcome;
 
 import org.apache.phoenix.pherf.PherfConstants.GeneratePhoenixStats;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
 import org.apache.phoenix.pherf.configuration.Column;
 import org.apache.phoenix.pherf.configuration.DataModel;
 import org.apache.phoenix.pherf.configuration.DataTypeMapping;
@@ -35,15 +48,8 @@ import org.apache.phoenix.pherf.workload.WriteWorkload;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import static org.junit.Assert.*;
+import com.jcabi.jdbc.JdbcSession;
+import com.jcabi.jdbc.Outcome;
 
 public class DataIngestIT extends ResultBaseTestIT {
 
@@ -146,4 +152,47 @@ public class DataIngestIT extends ResultBaseTestIT {
             fail("Failed to load data. An exception was thrown: " + e.getMessage());
         }
     }
+
+
+    @Test
+    /**
+     * Validates that Pherf can write data to a Multi-Tenant View in addition to 
+     * standard Phoenix tables.
+     */
+    public void testMultiTenantViewWriteWorkload() throws Exception {
+        // Arrange
+        Scenario scenario = parser.getScenarioByName("testMTWriteScenario");
+        WorkloadExecutor executor = new WorkloadExecutor();
+        executor.add(new WriteWorkload(util, parser, scenario, GeneratePhoenixStats.NO));
+        
+        // Act
+        try {
+            // Wait for data to load up.
+            executor.get();
+            executor.shutdown();
+        } catch (Exception e) {
+            fail("Failed to load data. An exception was thrown: " + e.getMessage());
+        }
+
+        assertExpectedNumberOfRecordsWritten(scenario);
+    }
+
+    private void assertExpectedNumberOfRecordsWritten(Scenario scenario) throws Exception,
+            SQLException {
+        Connection connection = util.getConnection(scenario.getTenantId());
+        String sql = "select count(*) from " + scenario.getTableName();
+        Integer count = new JdbcSession(connection).sql(sql).select(new Outcome<Integer>() {
+            @Override public Integer handle(ResultSet resultSet, Statement statement)
+                    throws SQLException {
+                while (resultSet.next()) {
+                    return resultSet.getInt(1);
+                }
+                return null;
+            }
+        });
+        assertNotNull("Could not retrieve count. " + count);
+        assertEquals("Expected 100 rows to have been inserted",
+                scenario.getRowCount(), count.intValue());
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c811cf68/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Scenario.java
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Scenario.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Scenario.java
index 7de96cc..6c949d8 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Scenario.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Scenario.java
@@ -18,15 +18,16 @@
 
 package org.apache.phoenix.pherf.configuration;
 
-import org.apache.commons.lang.builder.HashCodeBuilder;
-import org.apache.phoenix.pherf.util.PhoenixUtil;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 
 import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.phoenix.pherf.util.PhoenixUtil;
 
 @XmlRootElement(namespace = "org.apache.phoenix.pherf.configuration.DataModel")
 public class Scenario {
@@ -37,6 +38,7 @@ public class Scenario {
     private List<QuerySet> querySet = new ArrayList<>();
     private WriteParams writeParams;
     private String name;
+    private String tenantId;
 
     public Scenario() {
         writeParams = new WriteParams();
@@ -162,6 +164,19 @@ public class Scenario {
     public void setName(String name) {
         this.name = name;
     }
+    
+    /**
+     * Tenant Id used by connection of this query
+     * @return
+     */
+    @XmlAttribute
+    public String getTenantId() {
+        return tenantId;
+    }
+
+    public void setTenantId(String tenantId) {
+        this.tenantId = tenantId;
+    }
 
     public WriteParams getWriteParams() {
         return writeParams;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c811cf68/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/XMLConfigParser.java
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/XMLConfigParser.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/XMLConfigParser.java
index 393fa7e..93dc94c 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/XMLConfigParser.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/XMLConfigParser.java
@@ -18,16 +18,6 @@
 
 package org.apache.phoenix.pherf.configuration;
 
-import org.apache.phoenix.pherf.PherfConstants;
-import org.apache.phoenix.pherf.exception.FileLoaderException;
-import org.apache.phoenix.pherf.util.ResourceList;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Marshaller;
-import javax.xml.bind.Unmarshaller;
 import java.io.OutputStream;
 import java.nio.file.Path;
 import java.util.ArrayList;
@@ -35,6 +25,17 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.phoenix.pherf.PherfConstants;
+import org.apache.phoenix.pherf.exception.FileLoaderException;
+import org.apache.phoenix.pherf.util.ResourceList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 public class XMLConfigParser {
 
     private static final Logger logger = LoggerFactory.getLogger(XMLConfigParser.class);
@@ -134,6 +135,8 @@ public class XMLConfigParser {
         if (fullTableName.contains(".")) {
             ret = fullTableName.substring(fullTableName.indexOf(".") + 1, fullTableName.length());
         }
+        // Remove any quotes that may be needed for multi-tenant tables
+        ret = ret.replaceAll("\"", "");
         return ret;
     }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c811cf68/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/util/PhoenixUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/util/PhoenixUtil.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/util/PhoenixUtil.java
index 5b223b1..19b6bd2 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/util/PhoenixUtil.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/util/PhoenixUtil.java
@@ -18,21 +18,29 @@
 
 package org.apache.phoenix.pherf.util;
 
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_NAME;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_SCHEM;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
 import org.apache.phoenix.pherf.PherfConstants;
 import org.apache.phoenix.pherf.configuration.Column;
 import org.apache.phoenix.pherf.configuration.DataTypeMapping;
-
-import java.sql.*;
-import java.util.*;
-
 import org.apache.phoenix.pherf.configuration.Query;
 import org.apache.phoenix.pherf.configuration.QuerySet;
+import org.apache.phoenix.pherf.configuration.Scenario;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_SCHEM;
-import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_NAME;
-
 // TODO This class needs to be cleanup up a bit. I just wanted to get an initial placeholder in.
 public class PhoenixUtil {
 	private static final Logger logger = LoggerFactory.getLogger(PhoenixUtil.class);
@@ -80,11 +88,11 @@ public class PhoenixUtil {
         return DriverManager.getConnection(url, props);
     }
 
-    public boolean executeStatement(String sql) throws Exception {
+    public boolean executeStatement(String sql, Scenario scenario) throws Exception {
         Connection connection = null;
         boolean result = false;
         try {
-            connection = getConnection();
+            connection = getConnection(scenario.getTenantId());
             result = executeStatement(sql, connection);
         } finally {
             if (connection != null) {
@@ -262,8 +270,8 @@ public class PhoenixUtil {
      * @param tableName
      * @throws Exception
      */
-    public void updatePhoenixStats(String tableName) throws Exception {
+    public void updatePhoenixStats(String tableName, Scenario scenario) throws Exception {
         logger.info("Updating stats for " + tableName);
-        executeStatement("UPDATE STATISTICS " + tableName);
+        executeStatement("UPDATE STATISTICS " + tableName, scenario);
     }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c811cf68/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/WriteWorkload.java
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/WriteWorkload.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/WriteWorkload.java
index b6686c6..d0b99af 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/WriteWorkload.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/WriteWorkload.java
@@ -18,6 +18,21 @@
 
 package org.apache.phoenix.pherf.workload;
 
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
 import org.apache.phoenix.pherf.PherfConstants;
 import org.apache.phoenix.pherf.PherfConstants.GeneratePhoenixStats;
 import org.apache.phoenix.pherf.configuration.Column;
@@ -35,17 +50,6 @@ import org.apache.phoenix.pherf.util.RowCalculator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.math.BigDecimal;
-import java.sql.*;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Properties;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
 public class WriteWorkload implements Workload {
     private static final Logger logger = LoggerFactory.getLogger(WriteWorkload.class);
     private final PhoenixUtil pUtil;
@@ -163,15 +167,18 @@ public class WriteWorkload implements Workload {
         List<Future> writeBatches = getBatches(dataLoadThreadTime, scenario);
 
         waitForBatches(dataLoadTimeSummary, scenario, start, writeBatches);
-        
+
         // Update Phoenix Statistics
         if (this.generateStatistics == GeneratePhoenixStats.YES) {
         	logger.info("Updating Phoenix table statistics...");
-        	pUtil.updatePhoenixStats(scenario.getTableName());
+        	pUtil.updatePhoenixStats(scenario.getTableName(), scenario);
         	logger.info("Stats update done!");
         } else {
         	logger.info("Phoenix table stats update not requested.");
         }
+
+        // always update stats for Phoenix base tables
+        updatePhoenixStats(scenario.getTableName(), scenario);
     }
 
     private List<Future> getBatches(DataLoadThreadTime dataLoadThreadTime, Scenario scenario)
@@ -185,7 +192,7 @@ public class WriteWorkload implements Workload {
             List<Column>
                     phxMetaCols =
                     pUtil.getColumnsFromPhoenix(scenario.getSchemaName(),
-                            scenario.getTableNameWithoutSchemaName(), pUtil.getConnection());
+                            scenario.getTableNameWithoutSchemaName(), pUtil.getConnection(scenario.getTenantId()));
             int threadRowCount = rowCalculator.getNext();
             logger.info(
                     "Kick off thread (#" + i + ")for upsert with (" + threadRowCount + ") rows.");
@@ -221,6 +228,18 @@ public class WriteWorkload implements Workload {
                 .add(scenario.getTableName(), sumRows, (int) (System.currentTimeMillis() - start));
     }
 
+    /**
+     * TODO Move this method to PhoenixUtil
+     * Update Phoenix table stats
+     *
+     * @param tableName
+     * @throws Exception
+     */
+    public void updatePhoenixStats(String tableName, Scenario scenario) throws Exception {
+        logger.info("Updating stats for " + tableName);
+        pUtil.executeStatement("UPDATE STATISTICS " + tableName, scenario);
+    }
+
     public Future<Info> upsertData(final Scenario scenario, final List<Column> columns,
             final String tableName, final int rowCount,
             final DataLoadThreadTime dataLoadThreadTime) {
@@ -231,7 +250,7 @@ public class WriteWorkload implements Workload {
                 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                 Connection connection = null;
                 try {
-                    connection = pUtil.getConnection();
+                    connection = pUtil.getConnection(scenario.getTenantId());
                     long logStartTime = System.currentTimeMillis();
                     long
                             maxDuration =

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c811cf68/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_table.sql
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_table.sql b/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_table.sql
new file mode 100644
index 0000000..b6791bf
--- /dev/null
+++ b/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_table.sql
@@ -0,0 +1,31 @@
+/*
+  -- 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.
+*/
+CREATE TABLE IF NOT EXISTS PHERF.TEST_MULTI_TENANT_TABLE (
+    TENANT_ID CHAR(15) NOT NULL,
+    IDENTIFIER CHAR(3) NOT NULL,
+    ID CHAR(15) NOT NULL,
+    CREATED_DATE DATE,
+    FIELD VARCHAR,
+    SOME_INT INTEGER
+    CONSTRAINT PK PRIMARY KEY
+    (
+        TENANT_ID,
+        IDENTIFIER,
+        ID
+    )
+) VERSIONS=1,MULTI_TENANT=true

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c811cf68/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view.sql
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view.sql b/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view.sql
new file mode 100644
index 0000000..5f5d7ec
--- /dev/null
+++ b/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view.sql
@@ -0,0 +1 @@
+CREATE VIEW IF NOT EXISTS PHERF.TEST_VIEW (field1 VARCHAR, field2 VARCHAR) AS SELECT * FROM PHERF.TEST_MULTI_TENANT_TABLE
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c811cf68/phoenix-pherf/src/test/resources/scenario/test_scenario.xml
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/test/resources/scenario/test_scenario.xml b/phoenix-pherf/src/test/resources/scenario/test_scenario.xml
index fddf022..b5fe564 100644
--- a/phoenix-pherf/src/test/resources/scenario/test_scenario.xml
+++ b/phoenix-pherf/src/test/resources/scenario/test_scenario.xml
@@ -127,6 +127,25 @@
             <name>NEWVAL_STRING</name>
             <prefix>TSTPRFX</prefix>
         </column>
+        <column>
+            <type>CHAR</type>
+            <length>3</length>
+            <userDefined>true</userDefined>
+            <dataSequence>LIST</dataSequence>
+            <name>IDENTIFIER</name>
+            <valuelist>
+                <!-- Distributes according to specified values. These must total 100 -->
+                <datavalue distribution="60">
+                    <value>ABC</value>
+                </datavalue>
+                <datavalue distribution="20">
+                    <value>XYZ</value>
+                </datavalue>
+                <datavalue distribution="20">
+                    <value>LMN</value>
+                </datavalue>
+            </valuelist>            
+        </column>        
     </datamapping>
     <scenarios>
         <scenario tableName="PHERF.TEST_TABLE" rowCount="100" name="testScenarioRW">
@@ -201,5 +220,8 @@
                 <query id="q4" statement="select sum(SOME_INT) from PHERF.TEST_TABLE"/>
             </querySet>
         </scenario>
+        <!-- Test writing to a Multi-tenant View -->
+        <scenario tableName="PHERF.TEST_VIEW" tenantId="abcdefghijklmno" rowCount="100" name="testMTWriteScenario">
+        </scenario>
     </scenarios>
 </datamodel>
\ No newline at end of file